|
|
(15 intermediate revisions by the same user not shown) |
Line 147: |
Line 147: |
| Create a directory where AUR build files will go | | Create a directory where AUR build files will go |
|
| |
|
| {{bc| | | {{bc|1= |
| sudo mkdir /var/lib/pacman/aur | | sudo mkdir /var/lib/pacman/aur |
| sudo chmod 1777 /var/lib/pacman/aur | | sudo chmod 1777 /var/lib/pacman/aur |
| $ mkdir /var/lib/pacman/aur/$(whoami)
| | mkdir /var/lib/pacman/aur/$(whoami) |
| }} | | }} |
|
| |
|
| Build {{ic|yay}}. | | Build {{ic|yay}}. |
|
| |
|
| {{bc| | | {{bc|1=<nowiki> |
| $ cd /var/lib/pacman/aur/$(whoami)
| | cd /var/lib/pacman/aur/$(whoami) |
| $ git clone https://aur.archlinux.org/yay.git
| | git clone https://aur.archlinux.org/yay.git |
| $ cd yay
| | cd yay |
| $ makepkg -Ccisr
| | makepkg -Ccisr |
| }} | | </nowiki>}} |
|
| |
|
| The create the configuration file. | | The create the configuration file. |
Line 231: |
Line 231: |
|
| |
|
| Don't start {{ic|fail2ban}} or {{ic|sshd}} quite yet as they have configuration that needs to be done. | | Don't start {{ic|fail2ban}} or {{ic|sshd}} quite yet as they have configuration that needs to be done. |
|
| |
| == Docker ==
| |
|
| |
| This is only needed for OnlyOffice
| |
|
| |
| {{bc|
| |
| yay -Syu docker
| |
| sudo systemctl enable --now docker
| |
| }}
| |
|
| |
| == Nginx Web Server and Reverse Proxy ==
| |
|
| |
| These packages are typically used when setting up web applications like MediaWiki or Wordpress.
| |
|
| |
| {{bc|yay -Syu --needed apache-tools ca-certificates certbot-nginx mariadb nginx php-<nowiki>{acpu,fpm,gd,imagick,intl,redis,sodium}</nowiki> postgresql}}
| |
|
| |
| = Fail2Ban =
| |
|
| |
| {{hc|/etc/fail2ban/jail.local|2=
| |
| [DEFAULT]
| |
| bantime = 1d
| |
| destemail = root@bwt.com.de
| |
| sender = fail2ban@bwt.com.de
| |
| action = %(action_mwl)s
| |
| }}
| |
|
| |
| {{hc|/etc/fail2ban/jail.d/sshd.local|2=
| |
| [sshd]
| |
| enabled = true
| |
| filter = sshd
| |
| banaction = iptables
| |
| backend = systemd
| |
| maxretry = 5
| |
| findtime = 1d
| |
| bantime = 2w
| |
| ignoreip = 127.0.0.1/8
| |
| }}
| |
|
| |
| {{hc|/etc/fail2ban/jail.d/postfix-ispmail.local|2=
| |
| [postfix-ispmail]
| |
| enabled = true
| |
| filter = postfix
| |
| port = smtp,submission
| |
| banaction = iptables
| |
| backend = systemd
| |
| maxretry = 5
| |
| findtime = 1d
| |
| bantime = 2w
| |
| ignoreip = 192.99.246.231/32
| |
| }}
| |
|
| |
| {{hc|/etc/fail2ban/filter.d/postfix-ispmail.conf|2=
| |
| <nowiki>[INCLUDES]
| |
| before = common.conf
| |
|
| |
| [Definition]
| |
| _daemon = postfix(-\w+)?/(?:submission/|smtps/)?smtp[ds]
| |
| failregex = ^%(__prefix_line)slost connection after AUTH from \S+\[<HOST>\]$
| |
| ignoreregex =
| |
|
| |
| [Init]
| |
| journalmatch = _SYSTEMD_UNIT=postfix.service</nowiki>
| |
| }}
| |
|
| |
| = SSH Setup =
| |
|
| |
| Look for and edit the following lines in {{ic|/etc/ssh/sshd_config}}:
| |
|
| |
| {{hc|/etc/ssh/ssd_config|2=
| |
| <nowiki>Port <port>
| |
| AddressFamily <any|inet|inet6>
| |
| ListenAddress <ip4-address>
| |
| ListenAddress <ip6-address>
| |
|
| |
| LogLevel VERBOSE
| |
|
| |
| PermitRootLogin prohibit-password
| |
|
| |
| PubkeyAuthentication yes
| |
|
| |
| PasswordAuthentication no
| |
| PermitEmptyPasswords no
| |
|
| |
| ChallengeResponseAuthentication no
| |
|
| |
| UsePAM yes
| |
| AllowUsers <space-separated-list-of-users>
| |
|
| |
| AllowAgentForwarding no
| |
| AllowTcpForwarding no</nowiki>
| |
| }}
| |
|
| |
| Then make sure the {{ic|sshd}} service is enabled and running:
| |
|
| |
| {{bc|sudo systemctl enable --now sshd}}
| |
|
| |
| = MariaDB =
| |
|
| |
| == Data Directory ==
| |
|
| |
| If you want to put your databases somewhere other than the default {{ic|/var/lib/mysql}}:
| |
|
| |
| {{bc|
| |
| sudo mkdir <dir>
| |
| sudo chown -R mysql:mysql <dir>
| |
| }}
| |
|
| |
| == tmpfs for tmpdir ==
| |
|
| |
| The directory used by MariaDB for storing temporary files is named tmpdir. For example, it is used to perform disk based large sorts, as well as for internal and explicit temporary tables.
| |
|
| |
| Create the directory with appropriate permissions:
| |
|
| |
| {{bc|
| |
| sudo mkdir -pv <dir>
| |
| sudo chown mysql:mysql <dir>
| |
| }}
| |
|
| |
| Find the id and gid of the mysql user and group:
| |
|
| |
| {{hc|$ id mysql|2=
| |
| uid=27(mysql) gid=27(mysql) groups=27(mysql)}}
| |
|
| |
| Add to your /etc/fstab file.
| |
|
| |
| {{hc|/etc/fstab|2=
| |
| # Static information about the filesystems.
| |
| # See fstab(5) for details.
| |
|
| |
| # <file system> <dir> <type> <options> <dump> <pass>
| |
| ...
| |
| tmpfs /srv/sqltmp tmpfs rw,noatime,gid=933,uid=993,size=100M,mode=0750 0 0
| |
| ...
| |
| }}
| |
|
| |
| == Configuration File ==
| |
|
| |
| {{hc|/etc/my.cnf.d/server.cnf|2=
| |
| ...
| |
| [mysqld]
| |
| ...
| |
| datadir=<dir>
| |
| skip-networking
| |
| tmpdir=<dir>
| |
| ...
| |
| }}
| |
|
| |
| == Initial Setup ==
| |
|
| |
| {{bc|<nowiki>sudo mariadb-install-db --user=mysql --basedir=/usr --datadir=<dir></nowiki>}}
| |
|
| |
| == Start the Server ==
| |
|
| |
| {{bc|sudo systemctl enable --now mariadb}}
| |
|
| |
| == Security Settings ==
| |
|
| |
| {{bc|sudo mysql_secure_installation}}
| |
|
| |
| Create a user:
| |
|
| |
| {{hc|$ mysql -u root -p|2=
| |
| MariaDB> CREATE USER '<user>'@'localhost' IDENTIFIED BY '<password>';
| |
| MariaDB> GRANT ALL PRIVILEGES ON <database>.* TO '<USER>'@'localhost';
| |
| MariaDB> FLUSH PRIVILEGES;
| |
| MariaDB> quit
| |
| }}
| |
|
| |
| = Redis =
| |
|
| |
| Redis is used by several programs, including rspamd (e-mail), NextCloud, OnlyOffice, and Wordpress (optional).
| |
|
| |
| By default, {{ic|redis}} is already configured to bind to 127.0.0.1:6379, but the Unix socket is not enabled.
| |
|
| |
| {{hc|/etc/redis.conf|2=
| |
| ...
| |
| # Unix socket.
| |
| #
| |
| # Specify the path for the Unix socket that will be used to listen for
| |
| # incoming connections. There is no default, so Redis will not listen
| |
| # on a unix socket when not specified.
| |
| #
| |
| unixsocket /run/redis/redis.sock
| |
| unixsocketperm 700
| |
| ...
| |
| }}
| |
|
| |
| You will also need to add users to the {{ic|redis}} group so processes can access {{ic|redis}}
| |
|
| |
| {{bc|for username in http rspamd; do sudo usermod -G redis ${username}; done}}
| |
|
| |
| = E-mail =
| |
|
| |
| == Postfix ==
| |
|
| |
| === Create MariaDB Databases for Postfix ===
| |
|
| |
| {{bc|
| |
| CREATE DATABASE MAIL;
| |
| CREATE USER 'mailuser'@'localhost' IDENTIFIED BY '<password>';
| |
| CREATE USER 'mailadmin'@'localhost' IDENTIFIED BY '<password>';
| |
| GRANT ALL ON MAIL.* TO 'mailadmin'@'localhost';
| |
| GRANT SELECT ON MAIL.* TO 'mailuser'@'localhost';
| |
| }}
| |
|
| |
| {{bc|<nowiki>
| |
| CREATE TABLE IF NOT EXISTS `MAIL`.`virtual_domains` (
| |
| `id` int(11) NOT NULL auto_increment,
| |
| `name` varchar(50) NOT NULL,
| |
| PRIMARY KEY (`id`)
| |
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
| |
| </nowiki>}}
| |
|
| |
| {{bc|<nowiki>
| |
| CREATE TABLE IF NOT EXISTS `MAIL`.`virtual_users` (
| |
| `id` int(11) NOT NULL auto_increment,
| |
| `domain_id` int(11) NOT NULL,
| |
| `email` varchar(100) NOT NULL,
| |
| `password` varchar(150) NOT NULL,
| |
| PRIMARY KEY (`id`),
| |
| UNIQUE KEY `email` (`email`),
| |
| FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
| |
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
| |
| </nowiki>}}
| |
|
| |
| {{bc|<nowiki>
| |
| CREATE TABLE IF NOT EXISTS `MAIL`.`virtual_aliases` (
| |
| `id` int(11) NOT NULL auto_increment,
| |
| `domain_id` int(11) NOT NULL,
| |
| `source` varchar(100) NOT NULL,
| |
| `destination` varchar(100) NOT NULL,
| |
| PRIMARY KEY (`id`),
| |
| FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
| |
| ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
| |
| </nowiki>}}
| |
|
| |
| === Configure Postfix to Use MariaDB ===
| |
|
| |
| {{hc|/etc/postfix/mysql-virtual-mailbox-domains.cf|2=
| |
| user = mailuser
| |
| password = <password>
| |
| hosts = unix:/run/mysqld/mysqld.sock
| |
| dbname = MAIL
| |
| query = SELECT 1 FROM virtual_domains WHERE name='%s'
| |
| }}
| |
|
| |
| {{hc|/etc/postfix/mysql-virtual-mailbox-maps.cf|2=
| |
| user = mailuser
| |
| password = <password>
| |
| hosts = unix:/run/mysqld/mysqld.sock
| |
| dbname = MAIL
| |
| query = SELECT 1 FROM virtual_users WHERE email='%s'
| |
| }}
| |
|
| |
| {{hc|/etc/postfix/mysql-virtual-alias-maps.cf|2=
| |
| user = mailuser
| |
| password = <password>
| |
| hosts = unix:/run/mysqld/mysqld.sock
| |
| dbname = MAIL
| |
| query = SELECT destination FROM virtual_aliases WHERE source='%s'
| |
| }}
| |
|
| |
| {{hc|/etc/postfix/mysql-email2email.cf|2=
| |
| user = mailuser
| |
| password = <password>
| |
| hosts = unix:/run/mysqld/mysqld.sock
| |
| dbname = MAIL
| |
| query = SELECT email FROM virtual_users WHERE email='%s'
| |
| }}
| |
|
| |
| {{bc|<nowiki>
| |
| sudo postconf virtual_mailbox_domains=mysql:/etc/postfix/mysql-virtual-mailbox-domains.cf
| |
| sudo postconf virtual_mailbox_maps=mysql:/etc/postfix/mysql-virtual-mailbox-maps.cf
| |
| sudo postconf virtual_alias_maps=mysql:/etc/postfix/mysql-virtual-alias-maps.cf,mysql:/etc/postfix/mysql-email2email.cf
| |
| sudo chgrp postfix /etc/postfix/mysql-*.cf
| |
| sudo chmod 640 /etc/postfix/mysql-*.cf
| |
| </nowiki>}}
| |
|
| |
| === Configure Postfix for E-mail Filtering ===
| |
|
| |
| Add the following lines to the end of the {{ic|/etc/postfix/master.cf}} file:
| |
|
| |
| {{hc|/etc/postfix/master.cf|2=
| |
| ...
| |
| dovecot unix - n n - - pipe
| |
| flags=DRhu user=vmail:vmail argv=/usr/libexec/dovecot/deliver -f ${sender} -d ${recipient}
| |
| }}
| |
|
| |
| == Dovecot ==
| |
|
| |
| {{bc|
| |
| sudo groupadd -g 5000 vmail
| |
| sudo useradd -g vmail -u 5000 vmail -d /srv/imap -m
| |
| sudo chown -R vmail:vmail /srv/mail
| |
| sudo cp /usr/share/doc/dovecot/example-config/dovecot.conf /etc/dovecot
| |
| sudo cp -r /usr/share/doc/dovecot/example-config/conf.d /etc/dovecot
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/dovecot.conf|2=
| |
| ...
| |
|
| |
| # Protocols we want to be serving.
| |
| # Don't include submission -- postfix does that.
| |
| protocols = imap pop3 lmtp sieve
| |
| ....
| |
|
| |
| # Add these lines to the end of the file
| |
| # Or just before the include blocks
| |
|
| |
| service auth {
| |
|
| |
| unix_listener auth-client {
| |
| group = postfix
| |
| mode = 0660
| |
| user = postfix
| |
| }
| |
|
| |
| unix_listener auth-master {
| |
| group = vmail
| |
| mode = 0660
| |
| user = vmail
| |
| }
| |
|
| |
| user = root
| |
|
| |
| }
| |
|
| |
| service managesieve-login {
| |
|
| |
| inet_listener sieve {
| |
| port = 4190
| |
| }
| |
|
| |
| }
| |
|
| |
| service managesieve {
| |
| }
| |
|
| |
| protocol sieve {
| |
| managesieve_max_line_length = 65536
| |
| managesieve_implementation_string = dovecot
| |
| log_path = /var/log/dovecot-sieve-errors.log
| |
| info_log_path = /var/log/dovecot-sieve.log
| |
| }
| |
|
| |
| plugin {
| |
| sieve = ~/dovecot.sieve
| |
| sieve_global_path = /etc/dovecot/sieve/default.sieve
| |
| sieve_dir = ~/sieve
| |
| sieve_global_dir = /etc/dovecot/sieve/global/
| |
| }
| |
|
| |
| lda_mailbox_autocreate = yes
| |
| lda_mailbox_autosubscribe = yes
| |
|
| |
| protocol lda {
| |
| mail_plugins = $mail_plugins autocreate sieve quota
| |
| postmaster_address = postmaster@mydomain.com
| |
| hostname = mail.mydomain.com
| |
| auth_socket_path = /var/run/dovecot/auth-master
| |
| log_path = /var/log/dovecot-lda-errors.log
| |
| info_log_path = /var/log/dovecot-lda.log
| |
| }
| |
|
| |
| protocol lmtp {
| |
| mail_plugins = $mail_plugins autocreate sieve quota
| |
| log_path = /var/log/dovecot-lmtp-errors.log
| |
| info_log_path = /var/log/dovecot-lmtp.log
| |
| }
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/conf.d/10-auth.conf|2=
| |
| ...
| |
| #!include auth-system.conf.ext
| |
| !include auth-sql.conf.ext
| |
| ...
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/conf.d/auth-sql.conf.ext|2=
| |
| ...
| |
| #userdb {
| |
| # driver = sql
| |
| # args = /etc/dovecot/dovecot-sql.conf.ext
| |
| #}
| |
| ...
| |
| userdb {
| |
| driver = static
| |
| args = uid=vmail gid=vmail home=/srv/mail/%n@%d
| |
| }
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/conf.d/10-mail.conf|2=
| |
| ...
| |
| mail_location = maildir:/srv/mail/%n@%d/Maildir
| |
| ...
| |
| namespace inbox {
| |
| ...
| |
| separator = .
| |
| ...
| |
| }
| |
| ...
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/conf.d/10-master.conf|2=
| |
| ...
| |
| service lmtp {
| |
| unix_listener /var/spool/postfix/private/dovecot-lmtp {
| |
| group = postfix
| |
| mode = 0600
| |
| user = postfix
| |
| }
| |
| ...
| |
| }
| |
| ...
| |
| service auth {
| |
| ...
| |
| # Postfix smtp-auth
| |
| unix_listener /var/spool/postfix/private/auth {
| |
| mode = 0660
| |
| user = postfix
| |
| group = postfix
| |
| }
| |
| ...
| |
| }
| |
| ...
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/conf.d/10-ssl.conf|2=
| |
| ...
| |
| ssl = yes
| |
| ...
| |
| ssl_cert = </etc/letsencrypt/live/<domain>/fullchain.pem
| |
| ssl_key = </etc/letsencrypt/live/<domain>/privkey.pem
| |
| ...
| |
| ssl_ca = </etc/letsencrypt/live/<domain>/chain.pem
| |
| ...
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/conf.d/15-mailboxes.conf|2=
| |
| ...
| |
| mailbox INBOX.Drafts {
| |
| special_use = \Drafts
| |
| auto = subscribe
| |
| }
| |
| mailbox INBOX.Junk {
| |
| special_use = \Junk
| |
| auto = subscribe
| |
| autoexpunge = 30d
| |
| }
| |
| mailbox INBOX.Trash {
| |
| special_use = \Trash
| |
| auto = subscribe
| |
| autoexpunge = 30d
| |
| }
| |
| mailbox INBOX.Sent {
| |
| special_use = \Sent
| |
| auto = subscribe
| |
| }
| |
| ...
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/conf.d/20-imap.conf|2=
| |
| ...
| |
| protocol imap {
| |
| # Space separated list of plugins to load (default is global mail_plugins).
| |
| mail_plugins = $mail_plugins imap_sieve
| |
| ...
| |
| }
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/conf.d/20-lmtp.conf|2=
| |
| ...
| |
| protocol lmtp {
| |
| # Space separated list of plugins to load (default is global mail_plugins).
| |
| mail_plugins = $mail_plugins sieve
| |
| ...
| |
| }
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/conf.d/90-sieve.conf|2=
| |
| ...
| |
| sieve_after = /etc/dovecot/sieve-after
| |
| ...
| |
| sieve_plugins = sieve_imapsieve sieve_extprograms
| |
| ...
| |
| # From elsewhere to Junk folder
| |
| imapsieve_mailbox1_name = Junk
| |
| imapsieve_mailbox1_causes = COPY
| |
| imapsieve_mailbox1_before = file:/etc/dovecot/sieve/learn-spam.sieve
| |
|
| |
| # From Junk folder to elsewhere
| |
| imapsieve_mailbox2_name = *
| |
| imapsieve_mailbox2_from = Junk
| |
| imapsieve_mailbox2_causes = COPY
| |
| imapsieve_mailbox2_before = file:/etc/dovecot/sieve/learn-ham.sieve
| |
|
| |
| sieve_pipe_bin_dir = /etc/dovecot/sieve
| |
| sieve_global_extensions = +vnd.dovecot.pipe
| |
| }
| |
| }}
| |
|
| |
| {{bc|<nowiki>sudo mkdir /etc/dovecot/sieve{-after,}</nowiki>}}
| |
|
| |
| {{hc|/etc/dovecot/sieve-after/spam-to-folder.sieve|2=
| |
| require ["fileinto","mailbox"];
| |
|
| |
| if header :contains "X-Spam" "Yes" {
| |
| fileinto :create "INBOX.Junk";
| |
| stop;
| |
| }
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/sieve/learn-spam.sieve|2=
| |
| require ["vnd.dovecot.pipe", "copy", "imapsieve"];
| |
| pipe :copy "rspamd-learn-spam.sh";
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/sieve/learn-ham.sieve|2=
| |
| require ["vnd.dovecot.pipe", "copy", "imapsieve"];
| |
| pipe :copy "rspamd-learn-ham.sh";
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/dovecot-sql.conf.ext|2=
| |
| driver = mysql
| |
| connect = host=/run/mysqld/mysqld.sock dbname=MAIL user=mailuser password=<password>
| |
| default_pass_scheme = SHA256-CRYPT
| |
| password_query = SELECT email as user, password FROM virtual_users WHERE email='%u';
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/sieve/rspamd-learn-spam.sh|2=
| |
| #!/usr/bin/env sh
| |
| exec /usr/bin/rspamc learn_spam
| |
| }}
| |
|
| |
| {{hc|/etc/dovecot/sieve/rspamd-learn-ham.sh|2=
| |
| #!/usr/bin/env sh
| |
| exec /usr/bin/rspamc learn_ham
| |
| }}
| |
|
| |
| {{bc|<nowiki>
| |
| sudo sievec /etc/dovecot/sieve-after/spam-to-folder.sieve
| |
| sudo sievec /etc/dovecot/sieve/learn-spam.sieve
| |
| sudo sievec /etc/dovecot/sieve/learn-ham.sieve
| |
| sudo touch /var/log/{dovecot-lda-errors.log,dovecot-lda.log}
| |
| sudo touch /var/log/{dovecot-sieve-errors.log,dovecot-sieve.log}
| |
| sudo touch /var/log/{dovecot-lmtp-errors.log,dovecot-lmtp.log}
| |
| sudo mkdir -p /etc/dovecot/sieve/global
| |
| sudo chown vmail: -R /etc/dovecot/sieve
| |
| sudo chown vmail:mail /var/log/dovecot-*
| |
| sudo chown root:root /etc/dovecot/dovecot-sql.conf.ext
| |
| sudo chmod 600 /etc/dovecot/dovecot-sql.conf.ext
| |
| sudo chmod 600 /etc/dovecot/sieve/learn-{spam,ham}.sieve
| |
| sudo chmod 700 /etc/dovecot/sieve/rspamd-learn-{spam,ham}.sh
| |
| sudo chown vmail:vmail /etc/dovecot/sieve/learn-{spam,ham}.sieve
| |
| sudo chown vmail:vmail /etc/dovecot/sieve/rspamd-learn-{spam,ham}.sh
| |
| </nowiki>}}
| |
|
| |
| == Final Postfix Configuration ==
| |
|
| |
| {{bc|<nowiki>
| |
| sudo postconf virtual_transport=lmtp:unix:private/dovecot-lmtp
| |
| sudo postconf smtpd_sasl_type=dovecot
| |
| sudo postconf smtpd_sasl_path=private/auth
| |
| sudo postconf smtpd_sasl_auth_enable=yes
| |
| sudo postconf smtpd_tls_security_level=may
| |
| sudo postconf smtpd_tls_auth_only=yes
| |
| sudo postconf smtpd_tls_cert_file=/etc/letsencrypt/live/<domain>/fullchain.pem
| |
| sudo postconf smtpd_tls_key_file=/etc/letsencrypt/live/<domain>/privkey.pem
| |
| sudo postconf smtp_tls_security_level=may
| |
| sudo postconf smtpd_milters=inet:127.0.0.1:11332
| |
| sudo postconf non_smtpd_milters=inet:127.0.0.1:11332
| |
| sudo postconf milter_protocol=6
| |
| sudo postconf milter_mail_macros="i {mail_addr} {client_addr} {client_name} {auth_authen}"
| |
| </nowiki>}}
| |
|
| |
| {{hc|/etc/postfix/master.cf|2=
| |
| ...
| |
| submission inet n - - - - smtpd
| |
| -o syslog_name=postfix/submission
| |
| -o smtpd_tls_security_level=encrypt
| |
| -o smtpd_sasl_auth_enable=yes
| |
| -o smtpd_sasl_type=dovecot
| |
| -o smtpd_sasl_path=private/auth
| |
| -o smtpd_sasl_security_options=noanonymous
| |
| -o smtpd_sender_login_maps=mysql:/etc/postfix/mysql-email2email.cf
| |
| -o smtpd_sender_restrictions=reject_sender_login_mismatch
| |
| -o smtpd_sasl_local_domain=$myhostname
| |
| -o smtpd_client_restrictions=permit_sasl_authenticated,reject
| |
| -o smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject
| |
| ...
| |
| }}
| |
|
| |
| == Rspamd ==
| |
|
| |
| {{bc|sudo mkdir /etc/rspamd/conf.d}}
| |
|
| |
| {{hc|/etc/rspamd/override.d/milter_headers.conf|2=
| |
| extended_spam_headers = true;
| |
| }}
| |
|
| |
| {{hc|/etc/rspamd/override.d/classifier-bayes.conf|2=
| |
| autolearn = true;
| |
| }}
| |
|
| |
| {{bc|
| |
| sudo mkdir /var/lib/rspamd/dkim
| |
| sudo chown _rspamd:_rspamd /var/lib/rspamd/dkim
| |
| sudo rspamadm dkim_keygen -d <domain> -s $(date +%Y%m%d)
| |
| }}
| |
|
| |
| {{hc|/var/lib/rspamd/dkim/<domain>.YYYYMMDD.key|2=
| |
| <nowiki>-----BEGIN PRIVATE KEY-----
| |
| [base64 key]
| |
| -----END PRIVATE KEY-----</nowiki>
| |
| }}
| |
|
| |
| The second part of the output of {{ic|rspamadm dkim_keygen}} can be directly pasted into a DNS zone if you are running your own server. If you only have control of your domain name through a 3rd party:
| |
|
| |
| {| class="wikitable"
| |
| ! Type !! Host !! Value
| |
| |-
| |
| | TXT || @ || <nowiki>v=spf1 a mx ip4:<ip-address> -all</nowiki>
| |
| |-
| |
| | TXT || _dmarc || <nowiki>v=DMARC1; p=none; sp=none; rf=afrf; pct=100; ri=86400</nowiki>
| |
| |-
| |
| | TXT || YYYYMMDD._domainkey || <nowiki>v=DKIM1; k=rsa; p=AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789...</nowiki>
| |
| |}
| |
|
| |
| {{hc|/etc/rspamd/local.d/dkim_signing.conf|2=
| |
| path = "/var/lib/rspamd/dkim/$domain.$selector.key";
| |
| selector_map = "/etc/rspamd/dkim_selectors.map";
| |
| }}
| |
|
| |
| {{hc|/etc/rspamd/dkim_selectors.map|2=
| |
| <domain> YYYYMMDD
| |
| }}
| |
|
| |
| {{bc|sudo systemctl enable --now rspamd}}
| |
|
| |
| = PHP-FPM =
| |
|
| |
| Look for and edit the following lines in {{ic|/etc/php/php.ini}}:
| |
|
| |
| {{hc|/etc/php/php.ini|2=
| |
| [PHP]
| |
| open_basedir = /srv/http/:/home/:/tmp/:/usr/share/pear/:/usr/share/webapps/:/dev/urandom:/proc/meminfo
| |
| include_path = ".:/php/includes:/usr/share/pear"
| |
| upload_max_filesize = 8M
| |
|
| |
| extension=apcu
| |
| extension=dba
| |
| extension=exif
| |
| extension=gd
| |
| extension=gettext
| |
| extension=iconv
| |
| extension=imagick
| |
| extension=imap
| |
| extension=intl
| |
| extension=sodium
| |
| extension=ldap
| |
| extension=mysqli
| |
| zend_extension=opcache
| |
| extension=pdo_mysql
| |
| extension=soap
| |
|
| |
| [Date]
| |
| date.timezone = <timezone>
| |
|
| |
| [Pdo_mysql]
| |
| pdo_mysql.cache_size = 2000
| |
|
| |
| [opcache]
| |
| opcache.enable=1
| |
| opcache.enable_cli=1
| |
| opcache.memory_consumption=128
| |
| opcache.interned_strings_buffer=8
| |
| opcache.max_accelerated_files=10000
| |
| opcache.revalidate_freq=1
| |
| opcache.save_comments=1
| |
| }}
| |
|
| |
| == tmpfs for PHP Sessions ==
| |
|
| |
| {{hc|/etc/php/php.ini|2=
| |
| [Session]
| |
| session.save_path = "/srv/phptmp"
| |
| }}
| |
|
| |
| Find the id and gid of the mysql user and group:
| |
|
| |
| {{hc|$ id mysql|2=
| |
| uid=27(mysql) gid=27(mysql) groups=27(mysql)
| |
| }}
| |
|
| |
| {{hc|/etc/fstab|2=
| |
| # Static information about the filesystems.
| |
| # See fstab(5) for details.
| |
|
| |
| # <file system> <dir> <type> <options> <dump> <pass>
| |
| ...
| |
| tmpfs /srv/phptmp tmpfs rw,noatime,gid=27,uid=27,size=100M,mode=0750 0 0
| |
| ...
| |
| }}
| |
|
| |
| Then make sure the {{ic|php-fpm}} service is enabled and running:
| |
|
| |
| {{bc|sudo systemctl enable --now php-fpm}}
| |
|
| |
| = Nginx =
| |
|
| |
| == Main Configuration ==
| |
|
| |
| First, edit {{ic|/etc/nginx/nginx.conf}}:
| |
|
| |
| {{hc|/etc/nginx/nginx.conf|2=<nowiki>
| |
| user http;
| |
| worker_processes 1; # one(1) worker or equal the number of _real_ cpu cores. 4=4 core cpu
| |
| worker_priority 15; # renice workers to reduce priority compared to system processes for machine health. Worst case nginx will get ~25% system resources at nice=15
| |
| worker_rlimit_nofile 1024; # maximum number of open files
| |
| worker_cpu_affinity auto;
| |
|
| |
| events {
| |
| multi_accept on;
| |
| accept_mutex on; # serially accept() connections and pass to workers, efficient if workers gt 1
| |
| accept_mutex_delay 500ms; # worker process will accept mutex after this delay if not assigned. (default 500ms)
| |
| worker_connections 1024; # number of parallel or concurrent connections per worker_processes
| |
| }
| |
|
| |
| http {
| |
| charset utf-8;
| |
| aio on; # asynchronous file I/O, fast with ZFS, make sure sendfile=off
| |
| sendfile off; # on for decent direct disk IO, off for VMs
| |
| tcp_nopush off; # turning on requires sendfile=on
| |
| tcp_nodelay on; # Nagle buffering algorithm, used for keepalive only
| |
| server_tokens off; # version number in error pages
| |
| log_not_found off;
| |
| types_hash_max_size 4096;
| |
|
| |
| # MIME
| |
| include mime.types;
| |
| default_type application/octet-stream;
| |
|
| |
| # logging
| |
| access_log /var/log/nginx/access.log;
| |
| error_log /var/log/nginx/error.log warn;
| |
|
| |
| # SSL
| |
| ssl_session_timeout 1440m;
| |
| ssl_session_cache shared:le_nginx_SSL:10m;
| |
| ssl_session_tickets off;
| |
| ssl_prefer_server_ciphers off;
| |
|
| |
| # Diffie-Hellman parameter for DHE ciphersuites
| |
| ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
| |
|
| |
| # Mozilla Intermediate configuration
| |
| ssl_protocols TLSv1.2 TLSv1.3;
| |
| ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
| |
|
| |
| # OCSP Stapling
| |
| ssl_stapling on;
| |
| ssl_stapling_verify on;
| |
| resolver 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 208.67.222.222 208.67.220.220 valid=60s;
| |
| resolver_timeout 2s;
| |
|
| |
| # Size Limits
| |
| #client_body_buffer_size 8k;
| |
| #client_header_buffer_size 1k;
| |
| client_max_body_size 16M;
| |
| #large_client_header_buffers 4 4k/8k;
| |
|
| |
| ## From StackOverflow: for "upstream sent too big header while reading response header from upstream"
| |
| fastcgi_buffers 8 16k;
| |
| fastcgi_buffer_size 32k;
| |
|
| |
| # Timeouts, do not keep connections open longer then necessary to reduce
| |
| # resource usage and deny Slowloris type attacks.
| |
| client_body_timeout 5s; # maximum time between packets the client can pause when sending nginx any data
| |
| client_header_timeout 5s; # maximum time the client has to send the entire header to nginx
| |
| keepalive_timeout 75s; # timeout which a single keep-alive client connection will stay open
| |
| send_timeout 15s; # maximum time between packets nginx is allowed to pause when sending the client data
| |
|
| |
| ## General Options
| |
|
| |
| gzip off; # disable on the fly gzip compression due to higher latency, only use gzip_static
| |
| #gzip_http_version 1.0; # serve gzipped content to all clients including HTTP/1.0
| |
| gzip_static on; # precompress content (gzip -9) with an external script
| |
| #gzip_vary on; # send response header "Vary: Accept-Encoding"
| |
| gzip_proxied any; # allows compressed responses for any request even from proxies
| |
| ignore_invalid_headers on;
| |
| keepalive_requests 50; # number of requests per connection, does not affect SPDY
| |
| keepalive_disable none; # allow all browsers to use keepalive connections
| |
| max_ranges 1; # allow a single range header for resumed downloads and to stop large range header DoS attacks
| |
| msie_padding off;
| |
| open_file_cache max=1000 inactive=2h;
| |
| open_file_cache_errors on;
| |
| open_file_cache_min_uses 1;
| |
| open_file_cache_valid 1h;
| |
| output_buffers 1 512;
| |
| postpone_output 1440; # postpone sends to match our machine's MSS
| |
| read_ahead 512K; # kernel read head set to the output_buffers
| |
| recursive_error_pages on;
| |
| reset_timedout_connection on; # reset timed out connections freeing ram
| |
| server_name_in_redirect off; # if off, nginx will use the requested Host header
| |
| source_charset utf-8; # same value as "charset"
| |
|
| |
| ## Request limits
| |
| limit_req_zone $binary_remote_addr zone=gulag:1m rate=60r/m;
| |
|
| |
| ## Log Format
| |
| log_format main '$remote_addr $host $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $ssl_cipher $request_time';
| |
|
| |
| # load configs
| |
| include /etc/nginx/conf.d/*.conf;
| |
| include /etc/nginx/sites-enabled/*.conf;
| |
|
| |
| }
| |
| </nowiki>}}
| |
|
| |
| Make the {{ic|sites-available}} and {{ic|sites-enabled}} directories.
| |
|
| |
| {{bc|<nowiki>sudo mkdir /etc/nginx/sites-{available,enabled}</nowiki>}}
| |
|
| |
| == Non-Proxied Web Site ==
| |
|
| |
| === Create a Web Root ===
| |
|
| |
| {{bc|sudo mkdir /srv/http/<domain>}}
| |
|
| |
| If you don't have anything to put into the directory for the site, create an {{ic|index.php}} file.
| |
|
| |
| {{hc|/srv/http/<domain>/index.php|2=
| |
| <nowiki><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
| |
| <html xmlns="http://www.w3.org/1999/xhtml">
| |
| <head>
| |
| <title>Server Configuration Confirmation</title>
| |
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
| |
| </head>
| |
|
| |
| <body style="font-family:sans-serif;">
| |
|
| |
| <h1>Web server is properly configured!</h1>
| |
|
| |
| <?php echo "<h2>PHP is properly configured as well!</h2>" ?>
| |
|
| |
| <p>Time to add some content!</p>
| |
|
| |
| </body>
| |
| </html></nowiki>
| |
| }}
| |
|
| |
| === Configuration ===
| |
|
| |
| Make a site available by creating {{ic|/etc/nginx/sites-available/<domain>.conf}}:<br/>
| |
|
| |
| {{note|Remove the {{ic|#}}s after setting up Let's Encrypt.}}
| |
|
| |
| {{hc|/etc/nginx/sites-available/<domain>.conf|2=
| |
| <nowiki>server {
| |
| listen 80;
| |
| listen [::]:80;
| |
| server_name <domain>;
| |
|
| |
| # return 301 https://$host$request_uri;
| |
| #
| |
| #}
| |
| #
| |
| #server {
| |
| #
| |
| # listen 443 ssl http2;
| |
| # listen [::]:443 ssl http2;
| |
| # server_name <domain>;
| |
| #
| |
| # ssl_certificate /etc/letsencrypt/live/<domain>/fullchain.pem;
| |
| # ssl_certificate_key /etc/letsencrypt/live/<domain>/privkey.pem;
| |
| # ssl_trusted_certificate /etc/letsencrypt/live/<domain>/chain.pem;
| |
| #
| |
| # fastcgi_param HTTPS on;
| |
| #
| |
| # add_header Strict-Transport-Security max-age=15768000;
| |
|
| |
| root /srv/http/$host;
| |
| index index.html index.php;
| |
|
| |
| add_header Cache-Control "public";
| |
| add_header X-Frame-Options "DENY";
| |
|
| |
| access_log /var/log/nginx/access.log main buffer=32k;
| |
| error_log /var/log/nginx/error.log error;
| |
| limit_req zone=gulag burst=200 nodelay;
| |
|
| |
| # ACME challenge
| |
| location ^~ /.well-known {
| |
| allow all;
| |
| alias /var/lib/letsencrypt/$host/.well-known;
| |
| default_type "text/plain";
| |
| try_files $uri =404;
| |
| }
| |
|
| |
| location / {
| |
| try_files $uri $uri/ /index.php?$query_string;
| |
| }
| |
|
| |
| location ~ /(data|conf|bin|inc)/ {
| |
| deny all;
| |
| }
| |
|
| |
| location ~* \.(jpg|jpeg|gif|css|png|js|ico|html)$ {
| |
| access_log off;
| |
| expires max;
| |
| }
| |
|
| |
| location ~ \.php$ {
| |
| try_files $uri = 404;
| |
| fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
| |
| fastcgi_index index.php;
| |
| include fastcgi.conf;
| |
| }
| |
|
| |
| location ~ /\.ht {
| |
| deny all;
| |
| }
| |
|
| |
| }</nowiki>
| |
| }}
| |
|
| |
| == Proxied Web Site ==
| |
|
| |
| Rspamd comes with its own web interface. Configuring it is similar to a non-proxied site.<br/>
| |
|
| |
| {{note|Remove the {{ic|#}}s after setting up Let's Encrypt.}}
| |
|
| |
| {{hc|/etc/nginx/sites-available/<domain>.conf|2=
| |
| <nowiki>server {
| |
| listen 80;
| |
| listen [::]:80;
| |
| server_name <domain>;
| |
|
| |
| # return 301 https://$host$request_uri;
| |
| #
| |
| #}
| |
| #
| |
| #server {
| |
| #
| |
| # listen 443 ssl http2;
| |
| # listen [::]:443 ssl http2;
| |
| # server_name <domain>;
| |
| #
| |
| # ssl_certificate /etc/letsencrypt/live/<domain>/fullchain.pem;
| |
| # ssl_certificate_key /etc/letsencrypt/live/<domain>/privkey.pem;
| |
| # ssl_trusted_certificate /etc/letsencrypt/live/<domain>/chain.pem;
| |
| #
| |
| # add_header Strict-Transport-Security max-age=15768000;
| |
|
| |
| root /srv/http/$host;
| |
| index index.html index.php;
| |
|
| |
| add_header Cache-Control "public";
| |
| add_header X-Frame-Options "DENY";
| |
|
| |
| access_log /var/log/nginx/access.log main buffer=32k;
| |
| error_log /var/log/nginx/error.log error;
| |
| limit_req zone=gulag burst=200 nodelay;
| |
|
| |
| # ACME challenge
| |
| location ^~ /.well-known {
| |
| allow all;
| |
| alias /var/lib/letsencrypt/$host/.well-known;
| |
| default_type "text/plain";
| |
| try_files $uri =404;
| |
| }
| |
|
| |
| location / {
| |
| proxy_pass http://localhost:11334;
| |
|
| |
| proxy_set_header Upgrade $http_upgrade;
| |
| proxy_set_header Connection "upgrade";
| |
| proxy_set_header X-Real-IP $remote_addr;
| |
| proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
| |
| proxy_set_header Host $http_host;
| |
| proxy_set_header X-NginX-Proxy true;
| |
|
| |
| auth_basic "Username and Password Required";
| |
| auth_basic_user_file /etc/nginx/sites-enabled/htpasswd;
| |
| }
| |
|
| |
| }</nowiki>
| |
| }}
| |
|
| |
| == Basic Authorization ==
| |
|
| |
| Some proxied sites have inadequate or no authentication method of their own. Sometimes you may wish to provide an additional "bump in the road" for site access. Nginx can use an {{ic|htpasswd}} file to control access.
| |
|
| |
| {{bc|sudo htpasswd -c /etc/nginx/sites-enabled/htpasswd <user>}}
| |
|
| |
| You will then be prompted for a password, and to confirm the password. When finished, {{ic|htpasswd}} will create the file.
| |
|
| |
| {{hc|/etc/nginx/sites-enabled/htpasswd|2=
| |
| <username>:<password-hash>
| |
| }}
| |
|
| |
| {{tip|To update the file with more users or new passwords, omit the {{ic|-c}} parameter.}}
| |
|
| |
| To use Basic Authentication with nginx, put these lines in the appropriate {{ic|server}} or {{ic|location}} stanzas:
| |
|
| |
| {{bc|
| |
| auth_basic "Restricted By Username and Password";
| |
| auth_basic_user_file /etc/nginx/sites-enabled/htpasswd;
| |
| }}
| |
|
| |
| == SSL Certificate Authorization ==
| |
|
| |
| === Server Configuration ===
| |
|
| |
| {{hc|/etc/ssl/openssl.cnf|2=
| |
| [ CA_default ]
| |
|
| |
| dir = /srv/ssl # Where everything is kept
| |
|
| |
| certificate = $dir/ca.cert # The CA certificate
| |
|
| |
| private_key = $dir/private/ca.key # The private key
| |
| RNDFILE = $dir/private/.rand # The private random number file
| |
|
| |
| default_md = sha1 # use public key default MD
| |
| }}
| |
|
| |
| {{bc|1=<nowiki>
| |
| sudo mkdir -p /etc/ssl/ca/{certs,crl,private}
| |
| sudo mkdir /etc/ssl/ca/ca/certs/users
| |
| sudo touch /etc/ssl/ca/index.txt
| |
| echo ’01’ | sudo tee /etc/ssl/ca/crlnumber
| |
| </nowiki>}}
| |
|
| |
| === Creating the Server Certificate ===
| |
|
| |
| {{bc|1=
| |
| sudo openssl genrsa -des3 -out /srv/ssl/ca/private/ca.key 4096
| |
| sudo openssl req -new -x509 -days 1095 -key /srv/ssl/ca/private/ca.key -out /etc/ssl/ca/certs/ca.crt
| |
| sudo openssl ca -name CA_default -gencrl -keyfile /srv/ssl/ca/private/ca.key -cert /srv/ssl/ca/certs/ca.crt -out /srv/ssl/ca/private/ca.crl -crldays 1095
| |
| }}
| |
|
| |
| === Creating User Certificates ===
| |
|
| |
| {{tip|The first two password prompts will be for the signing request. The final one will be for the password for the certificate the user will import into their browser.}}
| |
|
| |
| {{bc|1=
| |
| sudo export USRCRTDR="/srv/ssl/ca/certs/users"
| |
| sudo openssl genrsa -des3 -out ${USRCRTDR}/USERNAME.key 1024
| |
| sudo openssl req -new -key ${USRCRTDR}/USERNAME.key -out ${USRCRTDR}/USERNAME.csr
| |
| sudo openssl x509 -req -days 1095 -in ${USRCRTDR}/USERNAME.csr -CA /etc/ssl/ca/certs/ca.crt -CAkey /etc/ssl/ca/private/ca.key -CAserial /etc/ssl/ca/serial -CAcreateserial -out ${USRCRTDR}/USERNAME.crt
| |
| sudo openssl pkcs12 -export -clcerts -in ${USRCRTDR}/USERNAME.crt -inkey ${USRCRTDR}/USERNAME.key -out ${USRCRTDR}/USERNAME.p12
| |
| }}
| |
|
| |
| {{tip|You can put this into a script to make it easier to issue new certificates.}}
| |
|
| |
| === Revoking User Certificates ===
| |
|
| |
| {{bc|1=
| |
| sudo openssl ca -name CA_Default -revoke /etc/ssl/ca/certs/users/USERNAME.crt -keyfile /etc/ssl/ca/private/ca.key -cert /etc/ssl/ca/certs/ca.crt
| |
| sudo openssl ca -name CA_Default -gencrl -keyfile /etc/ssl/ca/private/ca.key -cert /etc/ssl/ca/certs/ca.crt -out /etc/ssl/ca/private/ca.crl -crldays 1095
| |
| }}
| |
|
| |
| === Nginx Configuration ===
| |
|
| |
| If you want to use certificate authorization in nginx, add these lines to the appropriate {{ic|server}} stanzas:
| |
|
| |
| {{bc|
| |
| ssl_client_certificate /srv/ssl/certs/ca.crt;
| |
| ssl_crl /srv/ssl/private/ca.crl;
| |
| ssl_verify_client on;
| |
| }}
| |
|
| |
| == Finalization ==
| |
|
| |
| Enable your sites by using symlinks in {{ic|sites-enabled}} that point to the conf files in {{ic|sites-available}}
| |
|
| |
| {{bc|sudo ln -s ../sites-available/<domain>.conf /etc/nginx/sites-enabled/<domain>.conf}}
| |
|
| |
| Then make sure the {{ic|nginx}} service is enabled and running:
| |
|
| |
| {{bc|sudo systemctl enable --now nginx}}
| |
|
| |
| = Let's Encrypt =
| |
|
| |
| {{bc|sudo certbot certonly --nginx --agree-tos}}
| |
|
| |
| The {{ic|nginx}} plugin will guide you and help automate the process.
| |
|
| |
| Take note that the {{ic|nginx}} configuration in this guide takes into account the settings suggested by {{ic|certbot}}.
| |
|
| |
| == Automatic Renewal ==
| |
|
| |
| These will automatically renew your certificates every 2 months on the first Sunday of the month at 4am.
| |
|
| |
| === Systemd ===
| |
|
| |
| {{hc|/etc/systemd/system/certbot.service|2=
| |
| [Unit]
| |
| Description=Let's Encrypt renewal
| |
|
| |
| [Service]
| |
| Type=oneshot
| |
| ExecStart=/usr/bin/certbot renew --agree-tos --no-redirect
| |
| }}
| |
|
| |
| {{hc|/etc/systemd/system/certbot.timer|2=
| |
| [Unit]
| |
| Description=Bi-monthly renewal of Let's Encrypt's certificates
| |
|
| |
| [Timer]
| |
| OnCalendar=Sun *-1,3,5,7,9,11-1..7 04:00:00
| |
| RandomizedDelaySec=1h
| |
| Persistent=true
| |
|
| |
| [Install]
| |
| WantedBy=timers.target
| |
| }}
| |
|
| |
| === Crontab ===
| |
|
| |
| {{bc|0 4 1-7 2-12/2 0 /usr/bin/certbot renew --agree-tos --no-redirect}}
| |
|
| |
| = ISPmail Admin =
| |
|
| |
| Start with the [[Arch_Post-Installation_Checklist#Non-Proxied_Web_Site|Non-Proxied Web Site template]].
| |
|
| |
| Then, in the site's root:
| |
|
| |
| {{bc|<nowiki>
| |
| sudo wget 'https://www.ima.jungclaussen.com/dwn/dwn.php?v=0.9.6&f=.tar.gz'
| |
| sudo tar -xvf 'dwn.php?v=0.9.6&f=.tar.gz'
| |
| sudo mv ispmail*/htdocs/* ./
| |
| sudo rm -r 'dwn.php?v=0.9.6&f=.tar.gz' ispmail*
| |
| </nowiki>}}
| |
|
| |
| Then edit the configuration file:
| |
|
| |
| {{hc|<ispmail_root>/cfg/config.inc.php|2=
| |
| <?php
| |
|
| |
| // @package ISPmail_Admin
| |
| // @author Ole Jungclaussen
| |
| // @version 0.9.0
| |
|
| |
| // SHOW PHP ERRORS (DEBUGGING)
| |
|
| |
| // ini_set('display_startup_errors', 1);
| |
| // ini_set('display_errors', 1);
| |
| // error_reporting(-1);
| |
|
| |
| // DATABASE ACCESS
| |
|
| |
| define('IMA_CFG_DB_HOST', '127.0.0.1');
| |
| define('IMA_CFG_DB_PORT', '3306');
| |
| define('IMA_CFG_DB_USER', 'mailadmin');
| |
| define('IMA_CFG_DB_PASSWORD', '<password>');
| |
| define('IMA_CFG_DB_DATABASE', 'MAIL');
| |
|
| |
| // PASSWORD HASHES (enable only *one*)
| |
|
| |
| define('IMA_CFG_USE_SHA256_HASHES', true);
| |
| // define('IMA_CFG_USE_MD5_HASHES', true);
| |
|
| |
| // ACCESS CONTROL: uncomment the type you want to use.
| |
|
| |
| define('IMA_CFG_LOGIN', IMA_LOGINTYPE_ACCOUNT);
| |
| // define('IMA_CFG_LOGIN', IMA_LOGINTYPE_ADM);
| |
| // define('IMA_CFG_LOGIN', IMA_LOGINTYPE_ADMAUTO);
| |
|
| |
| // ADMINISTRATOR'S NAME AND PASSWORD
| |
|
| |
| define('IMA_CFG_ADM_USER', 'admin'); // admin username
| |
| define('IMA_CFG_ADM_PASS', '<password>'); // admin password
| |
|
| |
| // LISTS
| |
| // Spread long lists on multiple pages. Set number of maximum entries
| |
| // per page. Changes take effect after login/logout. If not defined,
| |
| // defaults to 65535.
| |
|
| |
| // define('IMA_LIST_MAX_ENTRIES', 200);
| |
| ?>
| |
| }}
| |
|
| |
| After [[Arch_Post-Installation_Checklist#Finalization|finalization]] you should now be able to log in and set up your virtual mailboxes.
| |
|
| |
| = Rainloop =
| |
|
| |
| Start with the [[Arch_Post-Installation_Checklist#Non-Proxied_Web_Site|Non-Proxied Web Site template]].
| |
|
| |
| Change the following sections of the nginx conf file:
| |
|
| |
| {{hc|/etc/nginx/sites-available/<domain>.conf|2=
| |
| ...
| |
| location ~ /data {
| |
| deny all;
| |
| }
| |
| ...
| |
| location ~ \.php$ {
| |
| fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
| |
| fastcgi_index index.php;
| |
| include fastcgi.conf;
| |
| fastcgi_split_path_info ^(.+\.php)(.*)$;
| |
| fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
| |
| }
| |
| ...
| |
| }}
| |
|
| |
| Download Rainloop
| |
|
| |
| {{bc|
| |
| sudo cd /srv/http/<domain>
| |
| sudo wget https://www.rainloop.net/repository/webmail/rainloop-community-latest.zip
| |
| }}
| |
|
| |
| Extract the zip file
| |
|
| |
| {{bc|sudo unzip rainloop-community-latest.zip}}
| |
|
| |
| Set the correct permissions on the files
| |
|
| |
| {{bc|
| |
| sudo find . -type d -exec chmod 755 {} \;
| |
| sudo find . -type f -exec chmod 644 {} \;
| |
| }}
| |
|
| |
| Set the correct owner on the whole web root
| |
|
| |
| {{bc|sudo chown -R http:http /srv/http/<dir>}}
| |
|
| |
| After you [[Arch_Post-Installation_Checklist#Finalize|finalize the setup]], you should now be able to access the Admini Panel at {{ic|<nowiki>http://<domain>/?admin</nowiki>}}. The default login is admin:12345
| |
|
| |
| From the Admin Panel, add your domain under Domains. Use the public-facing domain for the Name, and {{ic|localhost}} for the IMAP and SMTP servers.
| |
|
| |
| Under Login, set the Default Domain to {{ic|localhost}}.
| |
|
| |
| Optionally, you can enable contacts. You will need to manually set up a database and user, but that is the only configuration needed to do on your part.
| |
|
| |
| For Security, you should enable all of the Security options. You should also change the Admin Panel Access Credentials.
| |
|
| |
| Click on the power-off icon in the upper-right corner to finish with the Admin Panel.
| |
|
| |
| Navigate to {{ic|<nowiki>http://<domain></nowiki>}} to log in and access your mail.
| |
|
| |
| = OnlyOffice Document Server =
| |
|
| |
| On Arch, OnlyOffice can be installed via an [https://aur.archlinux.org/packages/onlyoffice-documentserver AUR package], with [https://helpcenter.onlyoffice.com/server/docker/document/docker-installation.aspx Docker], or with [https://snapcraft.io/onlyoffice-ds Snap].
| |
|
| |
| == AUR Package ==
| |
|
| |
| The [https://aur.archlinux.org/packages/onlyoffice-documentserver/ AUR package] was broken at the time of this writing.
| |
|
| |
| == Snap ==
| |
|
| |
| Snap did not work for me. However, this might have been due to the Snap's Redis service conflicting with that of the host's.
| |
|
| |
| == Docker ==
| |
|
| |
| The Docker version requires PostreSQL, RabbitMQ, and Redis to be set up. Be sure to install and configure those first.
| |
|
| |
| Once that is complete, set up the database and database user.
| |
|
| |
| {{bc|
| |
| sudo -u postgres psql -c "CREATE DATABASE onlyoffice;"
| |
| sudo -u postgres psql -c "CREATE USER onlyoffice WITH password 'onlyoffice';"
| |
| sudo -u postgres psql -c "GRANT ALL privileges ON DATABASE onlyoffice TO onlyoffice;"
| |
| }}
| |
|
| |
| Create the following directories.
| |
|
| |
| {{bc|sudo mkdir /var/{lib,log}/onlyoffice}}
| |
|
| |
| Issue one command to download and start the Docker instance.
| |
|
| |
| {{bc|<nowiki>
| |
| sudo docker run -i -t -d -p [port]:80 --restart=always \
| |
| -v /app/onlyoffice/DocumentServer/logs:/var/log/onlyoffice \
| |
| -v /app/onlyoffice/DocumentServer/lib:/var/lib/onlyoffice \
| |
| -v /app/onlyoffice/DocumentServer/db:/srv/psql onlyoffice/documentserver
| |
| </nowiki>}}
| |
|
| |
| Configure nginx to act as a proxy
| |
|
| |
| {{hc|/etc/nginx/sites-available/<domain>|2=<nowiki>
| |
| upstream docservice {
| |
| server <docker-ip>:8888;
| |
| }
| |
|
| |
| map $http_host $this_host {
| |
| "" $host;
| |
| default $http_host;
| |
| }
| |
|
| |
| map $http_x_forwarded_proto $the_scheme {
| |
| default $http_x_forwarded_proto;
| |
| "" $scheme;
| |
|
| |
| }
| |
|
| |
| map $http_x_forwarded_host $the_host {
| |
| default $http_x_forwarded_host;
| |
| "" $this_host;
| |
| }
| |
|
| |
| map $http_upgrade $proxy_connection {
| |
| default upgrade;
| |
| "" close;
| |
| }
| |
|
| |
| proxy_set_header Upgrade $http_upgrade;
| |
| proxy_set_header Connection $proxy_connection;
| |
| proxy_set_header X-Forwarded-Host $the_host;
| |
| proxy_set_header X-Forwarded-Proto $the_scheme;
| |
| proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
| |
|
| |
| server {
| |
| listen 80;
| |
| listen [::]:80;
| |
| server_name <domain>;
| |
| server_tokens off;
| |
| rewrite ^ https://$host$request_uri? permanent;
| |
| }
| |
|
| |
| server {
| |
|
| |
| listen 443 ssl http2;
| |
| listen [::]:443 ssl http2;
| |
| server_name ods.bwt.com.de;
| |
| server_tokens off;
| |
|
| |
| ssl_certificate /etc/letsencrypt/live/<domain>/fullchain.pem;
| |
| ssl_certificate_key /etc/letsencrypt/live/<domain>/privkey.pem;
| |
| ssl_trusted_certificate /etc/letsencrypt/live/<domain>/chain.pem;
| |
|
| |
| add_header Strict-Transport-Security max-age=31536000;
| |
| # add_header X-Frame-Options SAMEORIGIN;
| |
| add_header X-Content-Type-Options nosniff;
| |
|
| |
| access_log /var/log/nginx/access.log main buffer=32k;
| |
| error_log /var/log/nginx/error.log error;
| |
| limit_req zone=gulag burst=200 nodelay;
| |
|
| |
|
| |
| # ACME challenge
| |
| location ^~ /.well-known {
| |
| allow all;
| |
| alias /var/lib/letsencrypt/$host/.well-known;
| |
| default_type "text/plain";
| |
| try_files $uri =404;
| |
| }
| |
|
| |
| location / {
| |
| proxy_pass http://docservice;
| |
| proxy_http_version 1.1;
| |
| }
| |
| }
| |
| </nowiki>}}
| |
|
| |
| After [[Arch_Post-Installation_Checklist#Finalization|finalizing]], you should now be able to navigate to {{ic|<nowiki>https://<domain></nowiki>}} and see the OnlyOffice Document Server welcome page with a green checkmark indicating everything is running properly.
| |
Passwords & User Creation
Make sure root
has a password.
Make sure you have a primary user set up.
sudo useradd -m -u <id -ge 1000> -g users -G wheel,games,video,audio,optical,storage,scanner,power <user>
sudo passwd <user>
/etc/fstab
Time Zone
sudo ln -sf /usr/share/zoneinfo/<region>/<city> /etc/localtime
sudo hwclock --systohc
Localization
Un-comment your desired locales in /etc/locale.conf
, then run
sudo locale-gen
If you don't have the default /etc/locale.gen
file:
sudo rm /etc/locale.gen
sudo pacman -Syu glibc
Edit /etc/locale.conf
as you see fit
/etc/locale.conf
LANG=en_US.UTF-8
LANGUAGE=en_US
LC_COLLATE=POSIX
LC_MESSAGES=C
LC_CTYPE=en_US.UTF-8
LC_NUMERIC=en_US.UTF-8
LC_TIME=en_US.UTF-8
LC_MONETARY=en_US.UTF-8
LC_PAPER=en_US.UTF-8
LC_NAME=en_US.UTF-8
LC_ADDRESS=en_US.UTF-8
LC_TELEPHONE=en_US.UTF-8
LC_MEASUREMENT=en_US.UTF-8
LC_IDENTIFICATION=en_US.UTF-8
Set up /etc/vconsole.conf
with a keymap and (optionally) a font:
/etc/vconsole.conf
KEYMAP=us
FONT=Lat2-Terminus16
Initramfs
Look for and edit the following lines:
/etc/mkinitcpio.conf
MODULES=([amdgpu|bochs_drm|cirrus|i915|nouveau|(nvidia nvidia_modeset nvidia_uvm nvidia_drm)] [ehci_pci usb_storage]>)
HOOKS=(base udev autodetect modconf block [zfs] filesystems keyboard fsck [encrypt] keymap consolefont)
COMPRESSION=lz4
Networking
Host Name
Make sure a host name is set in /etc/hostname
Then edit /etc/hosts
/etc/hosts
127.0.0.1 localhost.localdomain locahost
::1 localhost.localdomain localhost
127.0.1.1 <hostname>.localdomain <hostname>
Static Addressing
Use systemd-networkd
when a machine will use a static address without consulting a DHCP server.
IPv4 Only
/etc/systemd/network/network.network
[Match]
MACAddress=<mac-address>
[Network]
Address=<ipv4-address>/<mask>
DNS=<ipv4-address>
Gateway=<ipv4-address>
LinkLocalAddressing=no
IPv6AcceptRA=no
IPv4 & IPv6
/etc/systemd/network/network.network
[Match]
MACAddress=<mac-address>
[Network]
Address=<ipv6-address>/<mask>
DNS=<ipv6-address>
Gateway=<ipv6-address>
Address=<ipv4-address>/<mask>
DNS=<ipv4-address>
Gateway=<ipv4-address>
Dynamic Addressing
It's preferable to use connman
or Network Manager
for dynamic addresses as systemd-networkd
doesn't play well with interfaces coming and going.
If you'd rather use systemd-networkd
for DHCP:
/etc/systemd/network/network.network
[Match]
MACAddress=<mac-address>
[Network]
DHCP=yes
[DHCP]
UseMTU=true
Packages
Mirror List
Install and use reflector
to automate the use and selection of mirrors.
sudo pacman -Syu reflector
sudo reflector -c <country> -p https -l 5 --sort rate --save /etc/pacman.d/mirrorlist
Yay
Make sure you have the base-devel
group installed.
sudo pacman -Syu --needed base-devel git
Create a directory where AUR build files will go
sudo mkdir /var/lib/pacman/aur
sudo chmod 1777 /var/lib/pacman/aur
mkdir /var/lib/pacman/aur/$(whoami)
Build yay
.
cd /var/lib/pacman/aur/$(whoami)
git clone https://aur.archlinux.org/yay.git
cd yay
makepkg -Ccisr
The create the configuration file.
~/.config/yay/config.json
{
"aururl": "https://aur.archlinux.org",
"buildDir": "/var/lib/pacman/aur/$USER",
"editor": "nano",
"editorflags": "",
"makepkgbin": "makepkg",
"makepkgconf": "",
"pacmanbin": "pacman",
"pacmanconf": "/etc/pacman.conf",
"tarbin": "bsdtar",
"redownload": "no",
"rebuild": "no",
"answerclean": "none",
"answerdiff": "all",
"answeredit": "",
"answerupgrade": "0",
"gitbin": "git",
"gpgbin": "gpg",
"gpgflags": "",
"mflags": "",
"sortby": "votes",
"gitflags": "",
"removemake": "yes",
"requestsplitn": 150,
"sortmode": 0,
"completionrefreshtime": 7,
"sudoloop": false,
"timeupdate": false,
"devel": true,
"cleanAfter": false,
"gitclone": true,
"provides": true,
"pgpfetch": true,
"upgrademenu": true,
"cleanmenu": true,
"diffmenu": true,
"editmenu": true,
"combinedupgrade": false,
"useask": false
}
General Utilities
These packages supplement the base system.
yay -Syu --needed adduser archey3 arj bind-tools bzip2 dmidecode dnsutils fail2ban git haveged htop hwdetect inxi iotop lshw lzop nano ncdu openssh p7zip pacman-contrib perl-rename pkgfile polkit ranger rsync strace sudo tmux unrar unzip vim whois zip
If you are not running inside a VM, you may also wish to add these packages:
yay -Syu hddtemp lm_sensors memtest86+ smartmontools
The havaged
service can be enabled and started right away as no configuration is needed.
sudo systemctl enable --now haveged
Your sensors need to be configured before starting the lm_sensors
service.
Note: This package is useless inside a VM.
sudo sensors-detect
sudo systemctl enable --now lm_sensors
Don't start fail2ban
or sshd
quite yet as they have configuration that needs to be done.