├── LICENSE
├── README.md
├── banner.gif
└── setup.sh
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 2-Clause License
2 |
3 | Copyright (c) 2020, Cristian Souza
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | # OpenBSD self-hosted
6 |
7 | This is the script I use to deploy my self-hosted services on top of OpenBSD. You are free to use and modify it according to your needs. Contributions are also welcome!
8 |
9 | **Tested on OpenBSD 6.7**
10 |
11 | ## Prerequisites
12 |
13 | 1. This script assumes you are running a fresh OpenBSD system on a public server (e.g., a VPS).
14 | 2. You must have a domain name pointing to your server's IP and subdomains (www, git, cloud, and mail).
15 |
16 | ## Goals
17 |
18 | 1. Self-hosting my most used services for privacy reasons.
19 | 2. Being able to customize my setup and add more features whenever I want.
20 |
21 | ## Software
22 |
23 | ### OpenBSD base system:
24 |
25 | - acme-client(1): for managing Let's Encrypt certificates.
26 | - httpd(8): nice and simple web server.
27 | - smtpd(8): for managing mails.
28 |
29 | ### Ports:
30 |
31 | - dovecot: for IMAP access.
32 | - Git and cgit: for managing source code repositories.
33 | - PHP: for running RainLoop and Nextcloud.
34 | - PostgreSQL: data storage for Nextcloud.
35 | - rspamd: spam filtering system.
36 |
37 | ### Web systems:
38 |
39 | - RainLoop: a nice UI for the email system.
40 | - Nextcloud: a safe place for all your files.
41 |
42 | Please remember to always check the source and not just run some random code on your machine.
43 |
44 | ## Installation
45 |
46 | Just run the following commands as root:
47 |
48 | `chmod +x setup.sh && ./setup.sh`
49 |
50 | You will be prompt for some basic information required for the configuration files.
51 |
52 | ## What you will get after installation:
53 |
54 | A fully functional self-hosted server for your git repositories, files, and mails.
55 |
--------------------------------------------------------------------------------
/banner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cristianzsh/openbsd-selfhosted/38c9cc2e1f41d64dd0d0e0499f90c2974d3e7a96/banner.gif
--------------------------------------------------------------------------------
/setup.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # OpenBSD self-hosted script.
3 | # https://github.com/crhenr/openbsd-selfhosted
4 |
5 | # Get basic information about the user.
6 | echo -n "What is your domain? "
7 | read domain
8 |
9 | echo -n "cgit username: "
10 | read git_title
11 |
12 | echo -n "Email username: "
13 | read email_user
14 |
15 | # Get passwords.
16 | echo -n "Email password (enter to autogenerate): "
17 | stty -echo
18 | read email_passwd
19 | stty echo
20 |
21 | if [ -z "$email_passwd" ]
22 | then
23 | email_passwd=$(openssl rand -base64 12)
24 | fi
25 | email_user_passwd=$(smtpctl encrypt $email_passwd)
26 |
27 | echo -n "\nPostgresql password (enter to autogenerate): "
28 | stty -echo
29 | read postgres_passwd
30 | stty echo
31 |
32 | if [ -z "$postgres_passwd" ]
33 | then
34 | postgres_passwd=$(openssl rand -base64 12)
35 | fi
36 |
37 | echo -n "\nNextcloud password (enter to autogenerate): "
38 | stty -echo
39 | read nextcloud_passwd
40 | stty echo
41 |
42 | if [ -z "$nextcloud_passwd" ]
43 | then
44 | nextcloud_passwd=$(openssl rand -base64 12)
45 | fi
46 |
47 | git_passwd=$(openssl rand -base64 12)
48 |
49 | # Colors:
50 | red="\033[0;31m"
51 | green="\033[0;32m"
52 | reset="\033[0m"
53 |
54 | # PHP options:
55 | memory_limit=-1
56 | max_input_time=180
57 | upload_max_filesize=512M
58 | post_max_size=32M
59 |
60 |
61 | # Install functions.
62 | run_acme() {
63 | echo "\n${green}[*] Creating acme-client.conf...${reset}"
64 | cat << EOF > /etc/acme-client.conf
65 | authority letsencrypt {
66 | api url "https://acme-v02.api.letsencrypt.org/directory"
67 | account key "/etc/acme/letsencrypt-privkey.pem"
68 | }
69 |
70 | authority letsencrypt-staging {
71 | api url "https://acme-staging-v02.api.letsencrypt.org/directory"
72 | account key "/etc/acme/letsencrypt-staging-privkey.pem"
73 | }
74 |
75 | domain $domain {
76 | alternative names { www.$domain, git.$domain cloud.$domain mail.$domain }
77 | domain key "/etc/ssl/private/$domain.key"
78 | domain certificate "/etc/ssl/$domain.crt"
79 | domain full chain certificate "/etc/ssl/$domain.pem"
80 | sign with letsencrypt
81 | }
82 | EOF
83 |
84 | echo "${green}[*] Creating initial httpd.conf...${reset}"
85 | cat << EOF > /etc/httpd.conf
86 | server "$domain" {
87 | listen on * port 80
88 |
89 | location "/.well-known/acme-challenge/*" {
90 | root "/acme"
91 | request strip 2
92 | }
93 | }
94 |
95 | EOF
96 |
97 | mkdir -p -m 700 /etc/ssl/private
98 | mkdir -p -m 755 /var/www/acme
99 | rcctl -f restart httpd
100 | echo "${green}[*] Generating certificates...${reset}"
101 | acme-client -v $domain
102 |
103 | if [[ $? != 0 ]]; then
104 | echo "${red}[-] acme-client failed! Exiting...${reset}"
105 | exit 1
106 | fi
107 |
108 | ocspcheck -N -o /etc/ssl/$domain.ocsp.pem /etc/ssl/$domain.pem
109 | (crontab -l 2>/dev/null; echo "0 0 * * * acme-client $domain && rcctl reload httpd") | crontab -
110 | (crontab -l 2>/dev/null; echo "0 * * * * ocspcheck -N -o /etc/ssl/$domain.ocsp.pem /etc/ssl/$domain.pem && rcctl reload httpd") | crontab -
111 | }
112 |
113 | install_git() {
114 | echo "${green}[*] Installing and configuring git and cgit...${reset}"
115 | pkg_add git cgit
116 | useradd -b /home -m -s /bin/ksh -p $git_passwd git
117 |
118 | cat << EOF > /var/www/conf/cgitrc
119 | # Enable caching of up to 1000 output entries
120 | cache-size=1000
121 |
122 | # Cache time to live
123 | cache-dynamic-ttl=5
124 | cache-repo-ttl=5
125 |
126 | # Specify the CSS URL
127 | css=/cgit.css
128 |
129 | # Show owner on index page
130 | enable-index-owner=0
131 |
132 | # Allow HTTP transport Git clone
133 | enable-http-clone=0
134 |
135 | # Enable ASCII art commit history graph on the log pages
136 | enable-commit-graph=1
137 |
138 | # Show number of affected files per commit on the log pages
139 | enable-log-file-count=1
140 |
141 | # Sort branches by date
142 | branch-sort=age
143 |
144 | # Add a cgit favicon
145 | favicon=/favicon.ico
146 |
147 | # Enable statistics per week, month and quarter
148 | max-stats=quarter
149 |
150 | # Set the title and heading of the repository index page
151 | root-title=$git_title's repositories
152 |
153 | # Set a subheading for the repository index page
154 | root-desc=
155 |
156 | # Allow download of tar.gz, tar.bz2 and zip-files
157 | snapshots=tar.gz
158 |
159 | ## List of common mimetypes
160 | mimetype.gif=image/gif
161 | mimetype.html=text/html
162 | mimetype.jpg=image/jpeg
163 | mimetype.jpeg=image/jpeg
164 | mimetype.pdf=application/pdf
165 | mimetype.png=image/png
166 | mimetype.svg=image/svg+xml
167 |
168 | ## Search for these files in the root of the default branch of repositories
169 | ## for coming up with the about page:
170 | readme=:README
171 |
172 | # Remove .git suffix
173 | remove-suffix=1
174 |
175 | scan-path=/srv/git
176 |
177 | # Disable adhoc downloads of this repo
178 | repo.snapshots=0
179 |
180 | # Disable line-counts for this repo
181 | repo.enable-log-linecount=0
182 |
183 | # Restrict the max statistics period for this repo
184 | repo.max-stats=month
185 | EOF
186 |
187 | cat <> /etc/httpd.conf
188 | # Git settings
189 | server "git.$domain" {
190 | listen on * tls port 443
191 |
192 | tls {
193 | certificate "/etc/ssl/$domain.pem"
194 | key "/etc/ssl/private/$domain.key"
195 | }
196 |
197 | location "/.well-known/acme-challenge/*" {
198 | root "/acme"
199 | request strip 2
200 | }
201 |
202 | location "/cgit.*" {
203 | root "/cgit"
204 | no fastcgi
205 | }
206 |
207 | root "/cgi-bin/cgit.cgi"
208 | fastcgi socket "/run/slowcgi.sock"
209 | }
210 |
211 | server "git.$domain" {
212 | listen on * port 80
213 | block return 301 "https://git.$domain\$REQUEST_URI"
214 | }
215 |
216 | EOF
217 |
218 | mkdir -p /var/www/srv/git
219 | chown git:git /var/www/srv/git
220 | mkdir -p /var/www/cgit/cache
221 | chown www:www /var/www/cgit/cache
222 |
223 | echo "slowcgi_flags=" >> /etc/rc.conf.local
224 | echo "httpd_flags=" >> /etc/rc.conf.local
225 |
226 | rcctl enable slowcgi httpd
227 | rcctl -f restart slowcgi httpd
228 | }
229 |
230 | install_nextcloud() {
231 | echo "${green}[*] Installing Nextcloud dependencies...${reset}"
232 | pkg_add postgresql-server php-7.3.19 php-curl-7.3.19 php-gd-7.3.19 php-intl-7.3.19 php-pdo_pgsql-7.3.19 php-zip-7.3.19
233 |
234 | cp /etc/php-7.3.sample/* /etc/php-7.3
235 | mkdir -p /var/www/etc/ssl
236 | cp /etc/resolv.conf /var/www/etc/resolv.conf
237 | cp /etc/ssl/cert.pem /var/www/etc/ssl/cert.pem
238 | cp /etc/ssl/openssl.cnf /var/www/etc/ssl/openssl.cnf
239 | chown -R www:www /var/www/etc
240 |
241 | echo "${green}[*] Configuring PostgreSQL...${reset}"
242 | mkdir /var/postgresql/data
243 | chown _postgresql:_postgresql /var/postgresql/data
244 |
245 | echo $postgres_passwd > /tmp/pwfile.txt
246 | su _postgresql -c 'initdb -D /var/postgresql/data -U postgres -A md5 --pwfile=/tmp/pwfile.txt'
247 | rm /tmp/pwfile.txt
248 |
249 | export PGPASSWORD=$postgres_passwd
250 | rcctl start postgresql
251 | su _postgresql -c "psql -d template1 -U postgres -c \"CREATE USER nextcloud WITH PASSWORD '$nextcloud_passwd';\""
252 | su _postgresql -c "psql -d template1 -U postgres -c \"CREATE DATABASE nextcloud\""
253 | su _postgresql -c "psql -d template1 -U postgres -c \"GRANT ALL PRIVILEGES ON DATABASE nextcloud to nextcloud;\""
254 | unset PGPASSWORD
255 |
256 | echo "${green}[*] Downloading Nextcloud...${reset}"
257 | ftp https://download.nextcloud.com/server/releases/nextcloud-18.0.6.tar.bz2
258 | tar xjvf nextcloud-18.0.6.tar.bz2 -C /var/www/
259 | rm nextcloud-18.0.6.tar.bz2
260 |
261 | echo "${green}[*] Configuring Nextcloud...${reset}"
262 | cat << EOF > /var/www/nextcloud/config/custom.config.php
263 | ((php_sapi_name() == 'cli') ? '/var/www' : '') . '/nextcloud/data',
266 | );
267 | EOF
268 |
269 | cat << EOF >> /etc/httpd.conf
270 | # Nextcloud settings
271 | server "cloud.$domain" {
272 | listen on * tls port 443
273 | root "/nextcloud"
274 | directory index "index.php"
275 |
276 | tls {
277 | certificate "/etc/ssl/$domain.pem"
278 | key "/etc/ssl/private/$domain.key"
279 | }
280 |
281 | connection max request body 537919488
282 | location "/.well-known/acme-challenge/*" {
283 | root "/acme"
284 | request strip 2
285 | }
286 |
287 | # Deny access to the specified files
288 | location "/db_structure.xml" { block }
289 | location "/.ht*" { block }
290 | location "/README" { block }
291 | location "/data*" { block }
292 | location "/config*" { block }
293 | location "/build*" { block }
294 | location "/tests*" { block }
295 | location "/config*" { block }
296 | location "/lib*" { block }
297 | location "/3rdparty*" { block }
298 | location "/templates*" { block }
299 | location "/data*" { block }
300 | location "/.user*" { block }
301 | location "/autotest*" { block }
302 | location "/occ*" { block }
303 | location "/issue*" { block }
304 | location "/indie*" { block }
305 | location "/db_*" { block }
306 | location "/console*" { block }
307 |
308 | location "/*.php*" {
309 | fastcgi socket "/run/php-fpm.sock"
310 | }
311 |
312 | location "/.well-known/host-meta" {
313 | block return 301 "/public.php?service=host-meta"
314 | }
315 |
316 | location "/.well-known/host-meta.json" {
317 | block return 301 "/public.php?service=host-meta-json"
318 | }
319 |
320 | location "/.well-known/webfinger" {
321 | block return 301 "/public.php?service=webfinger"
322 | }
323 |
324 | location "/.well-known/carddav" {
325 | block return 301 "/remote.php/dav/"
326 | }
327 |
328 | location "/.well-known/caldav" {
329 | block return 301 "/remote.php/dav/"
330 | }
331 | }
332 |
333 | server "cloud.$domain" {
334 | listen on * port 80
335 | block return 301 "https://cloud.$domain\$REQUEST_URI"
336 | }
337 |
338 | EOF
339 |
340 | sed -i "s/\(memory_limit *=*\).*/\1 $memory_limit/" /etc/php-7.3.ini
341 | sed -i "s/\(max_input_time *=*\).*/\1 $max_input_time/" /etc/php-7.3.ini
342 | sed -i "s/\(upload_max_filesize *=*\).*/\1 $upload_max_filesize/" /etc/php-7.3.ini
343 | sed -i "s/\(post_max_size *=*\).*/\1 $post_max_size/" /etc/php-7.3.ini
344 |
345 | sed -i "/opcache.enable=1/s/^;//" /etc/php-7.3.ini
346 | sed -i "/opcache.memory_consumption=128/s/^;//" /etc/php-7.3.ini
347 | sed -i "/opcache.interned_strings_buffer=8/s/^;//" /etc/php-7.3.ini
348 | sed -i "/opcache.max_accelerated_files=10000/s/^;//" /etc/php-7.3.ini
349 | sed -i "/opcache.save_comments=1/s/^;//" /etc/php-7.3.ini
350 |
351 | sed -i "s/;opcache.enable_cli=0/opcache.enable_cli=1/" /etc/php-7.3.ini
352 | sed -i "s/;opcache.revalidate_freq=2/opcache.revalidate_freq=1/" /etc/php-7.3.ini
353 |
354 | chown -R www:www /var/www/nextcloud
355 | rcctl enable postgresql php73_fpm httpd
356 | rcctl restart postgresql php73_fpm httpd
357 | }
358 |
359 | configure_email() {
360 | echo "${green}[*] Installing email dependencies...${reset}"
361 | pkg_add opensmtpd-extras opensmtpd-filter-rspamd dovecot dovecot-pigeonhole rspamd redis
362 |
363 | echo "${green}[*] Configuring OpenSMTPD...${reset}"
364 | cat << EOF > /etc/mail/smtpd.conf
365 | pki "mail.$domain" cert "/etc/ssl/$domain.crt"
366 | pki "mail.$domain" key "/etc/ssl/private/$domain.key"
367 |
368 | table aliases file:/etc/mail/aliases
369 | table credentials passwd:/etc/mail/credentials
370 | table virtuals file:/etc/mail/virtuals
371 |
372 | filter "rspamd" proc-exec "/usr/local/libexec/smtpd/filter-rspamd"
373 |
374 | listen on all tls pki "mail.$domain" hostname "mail.$domain" filter "rspamd"
375 | listen on egress port submission tls-require pki "mail.$domain" hostname "mail.$domain" auth filter "rspamd"
376 |
377 | action "local_mail" mbox alias
378 | action "domain_mail" maildir "/var/vmail/$domain/%{dest.user}" virtual
379 | action "outbound" relay
380 |
381 | match from any for domain "$domain" action "domain_mail"
382 | match from local for local action "local_mail"
383 |
384 | match from local for any action "outbound"
385 | match auth from any for any action "outbound"
386 | EOF
387 |
388 | printf "$email_user@$domain:$email_user_passwd:vmail:2000:2000:/var/vmail/$domain/$email_user::userdb_mail=maildir:/var/vmail/$domain/$email_user\n" > /etc/mail/credentials
389 |
390 | echo "${green}[*] Configuring Dovecot...${reset}"
391 | chmod 0440 /etc/mail/credentials
392 | useradd -c "Virtual Mail Account" -d /var/vmail -s /sbin/nologin -u 2000 -g =uid -L staff vmail
393 | mkdir /var/vmail
394 | chown _smtpd:_dovecot /etc/mail/credentials
395 | chown vmail:vmail /var/vmail
396 |
397 | cat << EOF > /etc/mail/virtuals
398 | abuse@$domain: $email_user@$domain
399 | hostmaster@$domain: $email_user@$domain
400 | postmaster@$domain: $email_user@$domain
401 | webmaster@$domain: $email_user@$domain
402 | $email_user@$domain: vmail
403 | EOF
404 |
405 | cat << EOF >> /etc/login.conf
406 |
407 | dovecot:\\
408 | :openfiles-cur=1024:\\
409 | :openfiles-max=2048:\\
410 | :tc=daemon:
411 | EOF
412 |
413 | cat << EOF > /etc/dovecot/local.conf
414 | auth_mechanisms = plain
415 | first_valid_uid = 2000
416 | first_valid_gid = 2000
417 | mail_location = maildir:/var/vmail/%d/%n
418 | mail_plugin_dir = /usr/local/lib/dovecot
419 | managesieve_notify_capability = mailto
420 | managesieve_sieve_capability = fileinto reject envelope encoded-character vacation subaddress comparator-i;ascii-numeric relational regex imap4flags copy include variables body enotify environment mailbox date index ihave duplicate mime foreverypart extracttext imapsieve vnd.dovecot.imapsieve
421 | mbox_write_locks = fcntl
422 | mmap_disable = yes
423 | namespace inbox {
424 | inbox = yes
425 | location =
426 | mailbox Archive {
427 | auto = subscribe
428 | special_use = \\Archive
429 | }
430 | mailbox Drafts {
431 | auto = subscribe
432 | special_use = \\Drafts
433 | }
434 | mailbox Junk {
435 | auto = subscribe
436 | special_use = \\Junk
437 | }
438 | mailbox Sent {
439 | auto = subscribe
440 | special_use = \\Sent
441 | }
442 | mailbox Trash {
443 | auto = subscribe
444 | special_use = \\Trash
445 | }
446 | prefix =
447 | }
448 | passdb {
449 | args = scheme=CRYPT username_format=%u /etc/mail/credentials
450 | driver = passwd-file
451 | name =
452 | }
453 | plugin {
454 | imapsieve_mailbox1_before = file:/usr/local/lib/dovecot/sieve/report-spam.sieve
455 | imapsieve_mailbox1_causes = COPY
456 | imapsieve_mailbox1_name = Junk
457 | imapsieve_mailbox2_before = file:/usr/local/lib/dovecot/sieve/report-ham.sieve
458 | imapsieve_mailbox2_causes = COPY
459 | imapsieve_mailbox2_from = Junk
460 | imapsieve_mailbox2_name = *
461 | sieve = file:~/sieve;active=~/.dovecot.sieve
462 | sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.environment
463 | sieve_pipe_bin_dir = /usr/local/lib/dovecot/sieve
464 | sieve_plugins = sieve_imapsieve sieve_extprograms
465 | }
466 | protocols = imap sieve
467 | service imap-login {
468 | inet_listener imaps {
469 | port = 0
470 | }
471 | }
472 | service managesieve-login {
473 | inet_listener sieve {
474 | port = 4190
475 | }
476 | inet_listener sieve_deprecated {
477 | port = 2000
478 | }
479 | }
480 | ssl_cert = /usr/local/lib/dovecot/sieve/report-ham.sieve
493 | require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
494 |
495 | if environment :matches "imap.mailbox" "*" {
496 | set "mailbox" "\${1}";
497 | }
498 |
499 | if string "\${mailbox}" "Trash" {
500 | stop;
501 | }
502 |
503 | if environment :matches "imap.user" "*" {
504 | set "username" "\${1}";
505 | }
506 |
507 | pipe :copy "sa-learn-ham.sh" [ "\${username}" ];
508 | EOF
509 |
510 | cat << EOF > /usr/local/lib/dovecot/sieve/report-spam.sieve
511 | require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
512 |
513 | if environment :matches "imap.user" "*" {
514 | set "username" "\${1}";
515 | }
516 |
517 | pipe :copy "sa-learn-spam.sh" [ "\${username}" ];
518 | EOF
519 |
520 | sed -i "/ssl_cert*/s/^/#/" /etc/dovecot/conf.d/10-ssl.conf
521 | sed -i "/ssl_key*/s/^/#/" /etc/dovecot/conf.d/10-ssl.conf
522 |
523 | sievec /usr/local/lib/dovecot/sieve/report-ham.sieve
524 | sievec /usr/local/lib/dovecot/sieve/report-spam.sieve
525 |
526 | cat << EOF > /usr/local/lib/dovecot/sieve/sa-learn-ham.sh
527 | #!/bin/sh
528 | exec /usr/local/bin/rspamc -d "\${1}" learn_ham
529 | EOF
530 |
531 | cat << EOF > /usr/local/lib/dovecot/sieve/sa-learn-spam.sh
532 | #!/bin/sh
533 | exec /usr/local/bin/rspamc -d "\${1}" learn_spam
534 | EOF
535 |
536 | chmod 0755 /usr/local/lib/dovecot/sieve/sa-learn-ham.sh
537 | chmod 0755 /usr/local/lib/dovecot/sieve/sa-learn-spam.sh
538 |
539 | mkdir /etc/mail/dkim && cd /etc/mail/dkim
540 | openssl genrsa -out private.key 1024
541 | openssl rsa -in private.key -pubout -out public.key
542 | chmod 0440 private.key
543 | chown root:_rspamd private.key && cd
544 |
545 | cat << EOF > /etc/rspamd/local.d/dkim_signing.conf
546 | domain {
547 | $domain {
548 | path = "/etc/mail/dkim/$domain.key";
549 | selector = "changethis";
550 | }
551 | }
552 | EOF
553 |
554 | echo "\n${green}[*] Installing RainLoop dependencies...${reset}"
555 | pkg_add php-7.3.19 php-curl-7.3.19 php-pdo_sqlite-7.3.19 php-zip-7.3.19 pecl73-mcrypt unzip-6.0p13
556 |
557 | echo "\n${green}[*] Downloading RainLoop...${reset}"
558 | ftp https://www.rainloop.net/repository/webmail/rainloop-latest.zip
559 | unzip rainloop-latest.zip -d /var/www/htdocs/rainloop
560 | rm rainloop-latest.zip
561 |
562 | cat << EOF >> /etc/httpd.conf
563 | # RainLoop settings
564 | server "mail.$domain" {
565 | listen on * tls port 443
566 | root "/htdocs/rainloop"
567 | directory index "index.php"
568 |
569 | tcp { nodelay, backlog 10 }
570 |
571 | tls {
572 | certificate "/etc/ssl/$domain.crt"
573 | key "/etc/ssl/private/$domain.key"
574 | }
575 |
576 | hsts {
577 | max-age 31556952
578 | preload
579 | }
580 |
581 | connection max request body 26214400
582 |
583 | location "/data*" {
584 | block return 403
585 | }
586 |
587 | location "*.php*" {
588 | fastcgi socket "/run/php-fpm.sock"
589 | }
590 | }
591 |
592 | server "mail.$domain" {
593 | listen on * port 80
594 | block return 301 "https://mail.$domain\$REQUEST_URI"
595 | }
596 |
597 | EOF
598 |
599 | mkdir /var/www/etc
600 | cp /etc/resolv.conf /var/www/etc/resolv.conf
601 | chown -R www:www /var/www/htdocs/rainloop
602 | rcctl enable smtpd dovecot redis rspamd httpd
603 | rcctl restart smtpd dovecot redis rspamd httpd
604 | }
605 |
606 | run_acme
607 | install_git
608 | install_nextcloud
609 | configure_email
610 |
611 | echo "
612 |
613 | ***************************************************************************************
614 | --> Important information
615 |
616 | ${green}[*]${reset} Domain: ${green}$domain${reset}
617 | ${green}[*]${reset} Email address: $email_user@$domain
618 | Password: ${red}$email_passwd${reset}
619 |
620 | ${green}[*]${reset} Passwords:
621 | - Git: ${red}$git_passwd${reset}
622 | - Postgres: ${red}$postgres_passwd${reset}
623 | - Nextcloud database: ${red}$nextcloud_passwd${reset}
624 |
625 | ${green}[*]${reset} Next steps:
626 | 1) Configure Nextcloud at cloud.$domain
627 | - Database user: nextcloud
628 | - Database password: $nextcloud_passwd
629 | - Database name: nextcloud
630 | 2) Change the RainLoop admin password at mail.$domain/?admin (default is 12345)
631 | 3) Add your public SSH key at /home/git/.ssh/authorized_keys
632 | 4) Create the DKIM and DMARC records:
633 | - Check the /etc/rspamd/local.d/dkim_signing.conf and /etc/mail/dkim/public.key
634 | files and follow the instructions given by your registrar.
635 |
636 | ***************************************************************************************
637 |
638 | OpenBSD self-hosted script.
639 | Made with <3 by @crhenr
640 | https://github.com/crhenr/openbsd-selfhosted
641 | "
642 |
--------------------------------------------------------------------------------