Wiki/Guides/Arch/02Server.md
2025-04-10 04:10:54 +02:00

1069 lines
32 KiB
Markdown

---
title: 02 Server
description:
published: true
date: 2024-11-24T11:38:12.406Z
tags:
editor: markdown
dateCreated: 2023-04-28T08:02:53.316Z
---
# Getting back in with the installation USB
First we have to get back into the installation medium to install the network components
You just start from USB again, Check your network, Mount the needed drives and chroot into the system
You might think, Why did I make you go trough this trouble?
Well, This routine should be common knowledge for Arch users, If you ever break your system, you now know how to get back into it and hopefully fix your system.
So once again so you don't have to go back to the previous guide.
ping archlinux.org
OK? Ctrl + C
mount the needed drives
mount /dev/nvme0n1p1 /mnt
Also mount boot if you need it, mount the second partition to /mnt/boot
mount /dev/nvme0n1p2 /mnt/boot
And finally chroot into the system so you can change whatever you need to change
arch-chroot /mnt
You should be root inside your installed system
# Installing DHCP
For network capabilities we need a DHCP client so install it
pacman -S dhcpcd
That's it
# Reboot into your Installation
Run the following command to escape from the chroot
exit
Run the following command to restart
reboot
Remove the USB when your screen turns black and it should boot into a login prompt
# Configure network
Configuring the network is easy with dhcpcd but first we need to know what device we want to enable
ip address
It should show you a bunch of devices, Ignore lo, there can be multiple, for me it is enp4s0.
so I run the following command to activate the network
sudo systemctl enable --now dhcpcd@enp4s0
You can then test with ping if it works, if it works you can go on, if not you can disable it again with sudo systemctl disable --now dhcpcd@enp4s0 and try other network devices listed by the previous command.
# Point Domains to your server
If you have any domains, you first need to edit their DNS records to point to your Server.
First we need our public IP so run the following command
host myip.opendns.com resolver1.opendns.com
Next up you go to your domain registrar, I can recommend Dynadot.com if you don't have one
You simply login go to domain settings, look for the DNS records and let it point to your IP It should look something like this
```
A domain.tld PublicIP
A *.domain.tld PublicIP
```
The `A` refers to IPv4, If you need IPv6 you just add both records again this time with `AAAA`
`domain.tld` should be replaced with your custom domain, the `*.domain.tld` is for all subdomains.
If you have a TTL setting, just put it on the lowest possible value and don't forget to save.
# Set Static IP for Server
You need a Static IP on your internal network so you can open ports on that internal IP without the device switching internal IP randomly
For this you need to login into your router, This can be a pain, If you have no idea I recommend resetting it and use the default password to login.
In the router interface you have to look for Static IP or DHCP reservation or something like that.
run the following command and look at the hardware address or MAC/link/ether address for your network device it should look something like this `ab:cd:f0:12:34:56`
ip address
Now you need to combine the mac address of the server with a static IP given by you, It might be good to plan out your network create different vlans like 192.168.1.X for your servers 192.168.2.X for your trusted devices 192.168.3.X for your smarthome devices and 192.168.4.X for a free wifi guest network, This way you have a seperated network for your home and servers, you can block all smarthome devices from phoning home by just blocking the subnet with 1 rule and you can seperate guests from your own devices. we are going to assume you made a subnet 192.168.1.X for your servers, and this server is 192.168.1.10.
So Mac Adress `ab:cd:f0:12:34:56` needs to be assigned the local IP of `192.168.1.10`.
Make sure you save, Then reboot your server and it should move over to the assigned local IP.
# Open two ports to your server
For now we are only going to open the ports 80 and 443 for http and https respectively
Still in your router interface you have to look for "port forward", Don't worry about clicking trough the menus, as long as you don't press save anywhere you should be fine :)
If you found the port forwarding screen you need to open ports 80 and 443 over TCP to the local static IP of your server. So in this example case
`192.168.1.10 TCP 80`
`192.168.1.10 TCP 443`
Make sure you save and you don't need to reboot anything for this.
Be careful with opening ports here, I would recommend against opening the SSH or the FTP ports, Keep it local which keeps it somewhat safe :)
Also remember that you don't need to open ports for local services, like mysql or any of the proxy ports, You also don't have to open ports for outgoing connections, It is just for incoming connections.
# Firewall
IPtables is present in the kernel and installed by default We use IPtables because docker networks don't play nice with nftables.
The default settings are fine we are leaving 80 and 443 closed, because the services we are going to host will be running from their own network. It is recomended to read up on iptables. Have a look at them and see what docker and fail2ban is changing over time. Do not change things other than steps in this guide unless you know what you are doing. See page *02 Server Iptables*
# Enable auto login
To make sure everything is getting started automatically after a reboot you can use autologin
edit the getty service file with the following command
sudo vim /etc/systemd/system/getty.target.wants/getty@tty1.service
Look for the following line
```
ExecStart=./sbin/agetty -o '-p -- \\u' --noclear - $TERM
```
And change it into this
```
ExecStart=-/sbin/agetty -o '-p -- \\u' --noclear --autologin USERNAME - $TERM
```
Save and exit
You can restart to ensure you are automatically logged in, It will still ask you for a password, but it should say Automatic Login after boot. If you want to log in with another user simply press enter (wrong password) and you can type another user when needed. press enter for your other user password and you are in!
# Install and Configure SSH
SSH or Secure SHell is a tool to access your server remotely, In our example we will only use it locally by simply not opening any ports in the router.
Simply install OpenSSH
sudo pacman -S openssh
We need to configure it properly so open the following file
sudo vim /etc/ssh/sshd_config
Uncomment LogLevel and change it to VERBOSE so we can use it with fail2ban
LogLevel VERBOSE
Now start and enable the service
sudo systemctl enable --now sshd
# Install Docker
Docker is the containerization software we are going to use, Every service will get its own container and network.
Install it with the following command
sudo pacman -S docker
now we just need to enable it with systemctl
sudo systemctl enable --now docker
Docker should be up and running.
# Install Docker Compose
Docker Compose is a front end for Docker, It allows us to set up containers and networks in an easy way.
Install it with the following command
sudo pacman -S docker-compose
Docker Compose parses yaml files, which are designed to be simple configuration files, spaces are everything here, so make sure you get the spacing right. It does allow us to set up containers quick and easy.
We configure 3 main things container details, volumes and networks
container or service details contain the name of the container, which image it should pull, when it should restart, etc.
volumes are like mounting points for persistant storage, For stuff like Configuration files, Databases, File storage, Stuff that must remain intact if you ever remove the container and rebuild it.
Networks are like virtual networks on the local network, they seperate the different services that don't need to talk to eachother. Services can be in multiple networks tho.
I hope the configuration files will make everything more clear, but this is everything you need to know for now.
# Shutdown your server
Aside from fail2ban, certbot, banner/motd and updating and the docker services themself your server is done. It is the perfect time to make some changes. mainly becuase the next sections require a lot of typing and the ability to copy/paste will be very welcome.
So shutdown your machine
sudo shutdown now
Remove the power cable and press the power button this will drain any power left in the machine. Now you can remove any GPU you needed for a video output, remove any peripherals like keyboard, monitors, and give your server a nice place in your house, Just connect the ethernet and power cable and simply press the power button once to start your server again.
Wait a minute and you should be able to login to your server from a different machine over your local network in our example the Local IP was 192.168.1.10 so our command will be the following
ssh username@192.168.1.10
Fill in your password associated with your username and press enter. If you run into problems here, double check the Firewall, SSH and static IP steps. Also make sure your home vlan has access to your server vlan if you chose to use different vlans.
# Banner and motd
Next up we are going to adjust the banner it will display on SSH password request
sudo vim /etc/issue
Add in the following content (you might need to \\ the \ ones)
```
_________
/ \
| Whatsup? |
\_______ /
\/
.--.
|o_o |
|:_/ |
// \ \
(| | )
/'\_ _/`\
\___)=(___/
```
Then we have the motd which will display after login
for this we will write a little script so it has up to date information
mkdir ~/Scripts
vim ~/Scripts/updatemotd.sh
Add in the following content
```
#!/bin/bash
printf " \e[34m/#\\ \e[0;0m_ \e[34m_ _
\e[34m/###\\ \e[0;0m __ _ _ __ ___| |__ \e[34m| (_)_ __ _ ___ __
\e[34m/#####\\ \e[0;0m/ _' | '__/ __| '_ \\ \e[34m| | | '_ \\| | | \\ \\/ /
\e[34m/##.-.##\\ \e[0;0m| (_| | | | (__| | | | \e[34m| | | | | | |_| |> <
\e[34m/##( )##\\ \e[0;0m\\__,_|_| \\___|_| |_| \e[34m|_|_|_| |_|\\__,_/_/\\_\\
\e[34m/#.-- --.#\\
\e[34m/' '\\
" > /etc/motd
printf "\e[34mMemory Usage: \e[0;0m" >> /etc/motd && free -m | grep Mem | awk '{ printf("%dMB/%dMB ", $3, $2) }' >> /etc/motd && free | grep Mem | awk '{ printf("%.2f%% used\n", $3*100/$2) }' >> /etc/motd
printf "\e[34mDisk Free: \e[0;0m" >> /etc/motd && df -h | awk '$NF=="/"{printf "root %s ", $4}' >> /etc/motd
printf "" && df -h | awk '$NF=="/data"{printf "data %s ", $4}' >> /etc/motd
printf "" && df -h | awk '$NF=="/music"{printf "data %s ", $4}' >> /etc/motd
printf "" && df -h | awk '$NF=="/video"{printf "data %s ", $4}' >> /etc/motd
printf "\n\e[34mLast Boot: \e[0;0m$(uptime)\n" >> /etc/motd
exit
```
Now we are going to create a Systemtimer which will run the script
sudo vim /etc/systemd/system/updatemotd.service
Add in the following (replace USSERNAME with your username!)
```
[Unit]
Description=Update the motd
Wants=updatemotd.timer
[Service]
Type=oneshot
ExecStart=/bin/bash /home/USERNAME/Scripts/updatemotd.sh
[Install]
WantedBy=multi-user.target
```
Now we need a timer file
sudo vim /etc/systemd/system/updatemotd.timer
Add in the following content
```
[Unit]
Description=Runs the update motd service every minute
Requires=updatemotd.service
[Timer]
Unit=updatemotd.service
OnBootSec=1min
OnUnitActiveSec=1min
[Install]
WantedBy=timers.target
```
And now we finally start the timer
sudo systemctl enable --now updatemotd.timer
You can exit the ssh and log back in to see the results
# Install and Configure Certbot
Certbot will create signed SSL certificates for you (For HTTPS websites)
We simply install it with the following command
sudo pacman -S certbot
First we need to open port 80 temporarily so that certbot can verify you own the domain.
sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT
Next we are going to request a certificate for every domain you pointed to this server.
sudo certbot certonly -d example.com
Just answer the questions and repeat the process for every other domain. Pick 1 if it asks for the authentication method.
Now we can restore the firewall settings again by running the following command
sudo iptables -D INPUT -p tcp -m tcp --dport 80 -j ACCEPT
Your certificates are only valid for 90 days, so we need to update them every once in a while, personally I just run a script every week that makes sure all certificates are valid
Create the script
vim ~/Scripts/renewcerts.sh
Add in the following content (replace USSERNAME with your username!)
```
#!/bin/bash
docker-compose -f /home/USERNAME/Docker/nginx/docker-compose.yml down
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
certbot renew
iptables -D INPUT -p tcp -m tcp --dport 80 -j ACCEPT
docker-compose -f /home/USERNAME/Docker/nginx/docker-compose.yml up -d
```
Next we need a service which actually executes the script so create the service file
sudo vim /etc/systemd/system/renewcerts.service
Add in the following content (replace USSERNAME with your username!)
```
[Unit]
Description=Updates all expiring certificates
Wants=renewcerts.timer
[Service]
Type=oneshot
ExecStart=/bin/bash /home/USERNAME/Scripts/renewcerts.sh
[Install]
WantedBy=multi-user.target
```
Next we need a timer which actually calls the service so create the timer file
sudo vim /etc/systemd/system/renewcerts.timer
Add in the following content
```
[Unit]
Description=Runs the update certificates service every week
Requires=renewcerts.service
[Timer]
OnCalendar=Tue 04:00
Persistent=true
[Install]
WantedBy=timers.target
```
Finally start and enable the timer so it will actually run
sudo systemctl enable --now renewcerts.timer
# Install and Configure Fail2Ban
Fail2Ban will read your logs for failed login attempts or other fishy things, when it crosses a certain amount of attempts it will block the IP using the firewall.
So first we are going to install fail2ban
sudo pacman -S fail2ban
Next enable and start the service
sudo systemctl enable --now fail2ban
Create a file where we will store all of our configuration
sudo vim /etc/fail2ban/jail.local
Replace the whole contents with the following
```
[INCLUDES]
before = paths-arch.conf
[DEFAULT]
## Settings
ignoreip = 127.0.0.1/8 ::1 192.168.1.1/16 172.20.0.0/16
findtime = 1h
maxretry = 3
bantime = 1h
bantime.increment = true
bantime.rndtime = 3600
bantime.multipliers = 1 3 5 12 24 168 4200 999999999
bantime.overalljails = true
banaction = action
## SSH Jail
[sshd]
enabled = true
```
For now we only set some default settings you can always overwrite them later on
ignoreip is pretty self explanitory, You can add your own IPs
findtime is the period in which these attempts are are allowed
maxretry is the number of attempts to trigger a ban
bantime is pretty self explanitory
bantime.increment this increments the bantime
bantime.rndtime adds a random time to the bantime to fool scripts
bantime.multipliers sets a custom ban time for repeated offenders
bantime.overalljails makes fail2ban check accross all jails so 1 attempt at 3 services is a ban
banaction is which action to perform, we will write a custom action in the next section
Finally under `[sshd]` we enabled sshd, we have to enable every service we add.
We will add more later depending on the services you want to activate
Save and exit the file
Now we need to create a banaction so fail2ban knows what to do when it needs to ban someone.
sudo vim /etc/fail2ban/action.d/action.conf
Add in the following lines
```
[Definition]
actionban = iptables -I INPUT -s <ip> -j REJECT
iptables -I FORWARD -s <ip> -j REJECT
iptables -I DOCKER-USER -s <ip> -j REJECT
echo "<matches>" >> /var/log/fail2ban.log
actionunban = iptables -D INPUT -s <ip> -j REJECT
iptables -D FORWARD -s <ip> -j REJECT
iptables -D DOCKER-USER -s <ip> -j REJECT
```
Here you can see that everytime it needs to ban someone it will simply execute some iptables commands that reject requests for docker and the host system.
I also put in the echo so it prints the why in the fail2ban log it can be handy for debugging but you can remove it.
Don't forget to restart the service to make the changes take effect
sudo systemctl restart fail2ban
You can use fail2ban-client to unban people or view some statistics
sudo fail2ban-client
Lets add some Aliases so viewing the banned list and unbanning people gets easier
WIP!
# Install and Configure Nginx
eNGINe X is a very powerful webserver, It can do many things and is highly configurable.
We will use it as a reverse proxy to forward requests to the correct container.
Create some folders in your home directory
mkdir -p ~/Docker/nginx
Now create a docker compose file in that directory
vim ~/Docker/nginx/docker-compose.yml
Add in the following text
```
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
restart: always
volumes:
- /data/nginx/config:/etc/nginx
- /data/nginx/log/error.log:/var/log/error.log
- /data/nginx/log/access.log:/var/log/access.log
- /etc/letsencrypt/:/etc/letsencrypt/
- /etc/localtime:/etc/localtime:ro
ports:
- 80:80
- 443:443
```
First we need to create a folder for the configuration
sudo mkdir -p /data/nginx/config
We need to add the nginx configuration file
sudo vim /data/nginx/config/nginx.conf
Add in the following text
```
# Global Settings
user nginx;
pid /var/run/nginx.pid;
worker_processes auto;
worker_rlimit_nofile 65535;
events {
multi_accept on;
worker_connections 1024;
}
# Web Traffic
http {
charset utf-8;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
server_tokens off;
error_log /var/log/error.log warn;
access_log /var/log/access.log;
proxy_cache_path /etc/nginx/cache keys_zone=one:500m max_size=1000m;
types_hash_max_size 2048;
types_hash_bucket_size 64;
client_max_body_size 16M;
client_body_buffer_size 16M;
client_header_buffer_size 16M;
large_client_header_buffers 2 16M;
# MIME
default_type application/octet-stream;
# Limits
limit_req_log_level warn;
limit_req_zone $binary_remote_addr zone=login:10m rate=10r/m;
# SSL
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_stapling on;
ssl_stapling_verify on;
# Services
include /etc/nginx/services/*.active;
}
```
We need to create the 2 log files so docker compose won't create directories
sudo touch /data/nginx/log/access.log /data/nginx/log/error.log
We also nened to create 2 directories which will house our auth
sudo mkdir -p /data/nginx/config/auth /data/nginx/config/services
Nginx should be good now, lets start the container
sudo docker-compose -f ~/Docker/nginx/docker-compose.yml up -d
Now we only need to setup fail2ban for Nginx, so create the following file
sudo vim /etc/fail2ban/filter.d/nginxx.local
add in the following content
```
[INCLUDES]
before = common.conf
[Definition]
failregex = ^<HOST>.*"(GET|POST).*" (400|401|403|404|405|406|407|423|429) .*$
```
This will ban everyone getting any of the error codes in the failregex line.
Now we need to activate the filter in our main fail2ban configuration file
sudo vim /etc/fail2ban/jail.local
Add the following to the bottom
```
## Nginx
[nginxx]
enabled = true
logpath = /data/nginx/log/access.log
```
Restart fail2ban to make the changes take effect
sudo systemctl restart fail2ban
# Install and Configure MariaDB
MariaDB is a drop in replacement for MySQL, which is a database used by many services.
First we create some folders
mkdir -p ~/Docker/mariadb
First we will create a docker compose file
vim ~/Docker/mariadb/docker-compose.yml
Add in the following text
```
version: '3'
services:
mariadb:
image: mariadb:latest
container_name: mariadb
restart: always
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --skip-innodb-read-only-compressed
volumes:
- /data/mariadb/data:/var/lib/mysql
- /data/mariadb/config:/etc/mysql/conf.d
- /data/mariadb/logs:/var/log/mysql
- /etc/localtime:/etc/localtime:ro
environment:
- MYSQL_ROOT_PASSWORD=SETAMYSQLROOTPASSWORDHERE
```
Be sure to set your mysql root password
Lets start the container
sudo docker-compose -f ~/Docker/mariadb/docker-compose.yml up -d
Now we only need to initialize the database
sudo docker exec -it mariadb mariadb-secure-installation
Answer the first 3 questions with No and the rest with Yes
# Install and Configure Nextcloud
Nextcloud is a great application, It is great for storing and syncing data, storing your contacts, bookmarks, passwords, calendar, tasks. It also has a great RSS reader, full office suite and many many more. I truly can't live without it. And neither should you which is why I picked it as the example for this guide
First we need to create a network for the service.
sudo docker network create --subnet=172.20.30.0/24 nextcloud
Next we are going to create some folders
mkdir -p ~/Docker/nextcloud
Now we will create a docker compose file
vim ~/Docker/nextcloud/docker-compose.yml
Add in the following text
```
version: '3'
services:
nextcloud:
image: nextcloud
container_name: nextcloud
restart: always
volumes:
- /etc/localtime:/etc/localtime:ro
- /data/nextcloud:/var/www/html
networks:
nextcloud:
ipv4_address: 172.20.30.10
networks:
nextcloud:
external: true
name: nextcloud
ipam:
config:
- subnet: 172.20.30.0/24
```
Now we need to add a server block for nextcloud to the Nginx config file so create a file that will be included by the main nginx config file
And create the file
sudo vim /data/nginx/config/services/nextcloud.active
add in the following text
```
server {
server_name example.com;
listen 443 ssl;
# Settings
autoindex off;
client_max_body_size 5000M;
# Locations
location / {
proxy_pass http://nextcloud:80;
proxy_http_version 1.1;
proxy_cache_bypass $http_upgrade;
proxy_ssl_server_name on;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_connect_timeout 600m;
proxy_send_timeout 600m;
proxy_read_timeout 600m;
}
location /.well-known/carddav {
return 301 $scheme://$host/remote.php/dav;
}
location /.well-known/caldav {
return 301 $scheme://$host/remote.php/dav;
}
location ~ /\.(?!well-known) {
deny all;
}
location = /favicon.ico {
log_not_found off;
}
location = /robots.txt {
log_not_found off;
}
# GZip
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml application/json application/javascript application/rss+xml application/atom+xml image/svg+xml;
# Headers
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN";
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: ws: wss: data: blob: 'unsafe-inline'; frame-ancestors 'self';" always;
add_header Permissions-Policy "interest-cohort=()" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" always;
# SSL
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
}
# Redirect
server {
listen 80;
server_name example.com;
return 301 https://example.com$request_uri;
}
```
Be sure to replace `example.com` 6 times
Now we need to add nextcloud to the mariadb and nginx networks, because it needs a database and a proxy.
open the nginx compose file
vim ~/Docker/nginx/docker-compose.yml
add the nextcloud network so it looks like this
```
version: '3'
services:
nginx:
image: nginx:latest
container_name: nginx
restart: always
volumes:
- /data/nginx/config:/etc/nginx
- /data/nginx/log/error.log:/var/log/error.log
- /data/nginx/log/access.log:/var/log/access.log
- /etc/letsencrypt/:/etc/letsencrypt/
- /etc/localtime:/etc/localtime:ro
ports:
- 80:80
- 443:443
- 8448:8448
networks:
nextcloud:
ipv4_address: 172.20.30.20
networks:
nextcloud:
external: true
name: nextcloud
```
open the mariadb compose file
vim ~/Docker/mariadb/docker-compose.yml
add the nextcloud network so it looks like this
```
version: '3'
services:
mariadb:
image: mariadb:latest
container_name: mariadb
restart: always
command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW --skip-innodb-read-only-compressed
volumes:
- /data/mariadb/data:/var/lib/mysql
- /data/mariadb/config:/etc/mysql/conf.d
- /data/mariadb/logs:/var/log/mysql
- /etc/localtime:/etc/localtime:ro
environment:
- MYSQL_ROOT_PASSWORD=SETAMYSQLROOTPASSWORDHERE
networks:
nextcloud:
ipv4_address: 172.20.30.30
networks:
nextcloud:
external: true
name: nextcloud
```
Now we are going to start the nextcloud container and restart the nginx and mariadb containers.
sudo docker-compose -f ~/Docker/nextcloud/docker-compose.yml up -d
sudo docker-compose -f ~/Docker/nginx/docker-compose.yml down && sudo docker-compose -f ~/Docker/nginx/docker-compose.yml up -d
sudo docker-compose -f ~/Docker/mariadb/docker-compose.yml down && sudo docker-compose -f ~/Docker/mariadb/docker-compose.yml up -d
Nextcloud should be accessable from your browser using the domain you chose.
If you have not setup your dns records but only adjusted your .active file for nginx you need to do 2 things first before you go on.
- make sure you have chosen a domain (nextcloud.example.com) and used it in your .active file for nginx.
- make sure you have valid certificates for this domain. if not go back to the certbot part so you can repeat those instructions for your nextcloud domain.
But first we need to create a database, a user and set the permissions.
You can get into the database with the following command (only if mariadb is running)
sudo docker exec -it mariadb mariadb -p
Enter the Mysql root password you provided during the creation of the mariadb container and you should be in.
Now run the following commands to create a database, create a user with privileges, and make them take effect.
create database nextcloud;
create user nextcloud@'172.20.30.10' identified by 'NEXTCLOUDDATABASEPASSWORD';
grant all privileges on nextcloud.* to nextcloud@'172.20.30.10';
flush privileges;
You can exit the mysql prompt with `exit;` and then pressing enter.
Now we just need to go to example.com and follow the steps
The Database is nextcloud, the user is nextcloud, The IP is 172.20.30.30:3306 and the password is what you gave it.
We also need to force HTTPS, else it will give problems since we are running from behind a proxy
sudo vim /data/nextcloud/config/config.php
Add in the following line preferrrably under the overwrite.cli.url line.
```
'overwriteprotocol' => 'https',
```
Nextcloud requires some tasks to be executed every 5 minutes, for that we are going to use systemd timers, like we did for certbot
Create a little script
vim ~/Scripts/nextcloudcron.sh
add in the following content
```
#!/bin/bash
docker exec -u 33 -t nextcloud php -f /var/www/html/cron.php
exit
```
Create a systemd service
sudo vim /etc/systemd/system/nextcloudcron.service
Add in the following content
```
[Unit]
Description=Runs Nextcloud Cron
Wants=nextcloudcron.timer
[Service]
Type=oneshot
ExecStart=/bin/bash /home/USERNAME/Scripts/nextcloudcron.sh
[Install]
WantedBy=multi-user.target
```
Create a timer file
sudo vim /etc/systemd/system/nextcloudcron.timer
and add in the following content
```
[Unit]
Description=Runs Nextcloud Cron
Requires=nextcloudcron.service
[Timer]
Unit=nextcloudcron.service
OnBootSec=5min
OnUnitActiveSec=5min
[Install]
WantedBy=timers.target
```
Finally start the timer
sudo systemctl enable --now nextcloudcron.timer
Nextcloud should be all good and ready to go, You can check the persistance by completely deleting all containers and all volumes, When you start it again all your stuff should still be there :)
Nextcloud has its own Brute force protection, but we still are going to add a fail2ban filter because we want attackers to be banned from all services and not just nextcloud.
So lets create a new nextcloud filter
sudo vim /etc/fail2ban/filter.d/nextcloud.local
add in the following content
```
[Definition]
failregex=^{"reqId":".*","remoteAddr":".*","app":"core","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)","level":2,"time":".*"}$
^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":".*","method":".*","url":".*","message":"Login failed: '.*' \(Remote IP: '<HOST>'\)".*}$
^{"reqId":".*","level":2,"time":".*","remoteAddr":".*","user":".*","app":".*","method":".*","url":".*","message":"Login failed: .* \(Remote IP: <HOST>\).*}$
```
Now add the filter to your main fail2ban config file
sudo vim /etc/fail2ban/jail.local
Add the following to the end of the file
```
## Nextcloud
[nextcloud]
filter = nextcloud
enabled = true
logpath = /data/nextcloud/data/nextcloud.log
```
restart fail2ban to make it take effect
sudo systemctl restart fail2ban
# Updating the Server
To maintain the system we simply need to update it by running the following command
sudo pacman -Syu
To update the docker containers we need to pull every container and then restart it, it would be a lot of work every time you want to upgrade. It is easier to create a script instead of manually typing all the commands every time.
So create a file
vim ~/Scripts/update-docker.sh
put in the following text
```
#!/bin/bash
# Update Nginx
docker-compose -f /home/USERNAME/Docker/nginx/docker-compose.yml pull
docker-compose -f /home/USERNAME/Docker/nginx/docker-compose.yml down
docker-compose -f /home/USERNAME/Docker/nginx/docker-compose.yml up -d --remove-orphans
# Update MariaDB
docker-compose -f /home/USERNAME/Docker/mariadb/docker-compose.yml pull
docker-compose -f /home/USERNAME/Docker/mariadb/docker-compose.yml down
docker-compose -f /home/USERNAME/Docker/mariadb/docker-compose.yml up -d --remove-orphans
# Update Nextcloud
docker-compose -f /home/USERNAME/Docker/nextcloud/docker-compose.yml pull
docker-compose -f /home/USERNAME/Docker/nextcloud/docker-compose.yml down
docker-compose -f /home/USERNAME/Docker/nextcloud/docker-compose.yml up -d --remove-orphans
```
You should add any services you add to this simple script so all containers get updated
Save, exit and then make it executable with the following command
sudo chmod u+x update-docker.sh
You can now run the script to update all docker containers
# Let the script run with pacman
Why mess around with 2 commands, when you can simply force the docker-update.sh script to run when you update your system using pacman. We can do this very easy with pacman hooks
create a file in the hooks directory for docker
sudo vim /usr/share/libalpm/hooks/docker.hook
Add in the following text
```
[Trigger]
Operation = Upgrade
Type = Package
Target = *
[Action]
Description = Update Docker Containers
When = PostTransaction
Exec = /bin/bash /home/USERNAME/Scripts/update-docker.sh
```
Save and exit and try to update your system, if you are lucky you have an update and you can see the script in action after the update.
# Next
For now I would continue the guide Terminal and Programming are quite useful for a server, I would also recommend reading the maintenance part of the guide. But you can skip basic programs, office, gaming, etc
When you are done you can go to my Docker guide, and install any service your heart desires :)