From adef3f4ccc585990defcfafe937cc9e02b466572 Mon Sep 17 00:00:00 2001 From: tavo-wasd Date: Thu, 21 Sep 2023 23:00:53 -0600 Subject: [PATCH] bring guides from self hosted repo --- self-hosting/README.md | 23 ++ self-hosting/bypass-cgnat/README.md | 3 + .../backup/wireguard-config/wg0-local.conf | 7 + .../backup/wireguard-config/wg0-server.conf | 6 + .../bypass-cgnat/iptables/iptables-down.sh | 22 ++ .../bypass-cgnat/iptables/iptables-up.sh | 22 ++ self-hosting/bypass-cgnat/local.sh | 43 ++++ self-hosting/bypass-cgnat/server.sh | 64 +++++ self-hosting/services/ejabberd/README.md | 149 +++++++++++ .../services/examplereverseproxy.conf | 12 + self-hosting/services/examplewebsite.conf | 22 ++ self-hosting/services/nextcloud/README.md | 235 ++++++++++++++++++ .../services/nextcloud/nextcloud.conf | 166 +++++++++++++ self-hosting/services/onlyoffice/README.md | 43 ++++ system_administration/secure-ssh/README.md | 80 ++++++ .../wireless-network-debian}/README.md | 2 +- 16 files changed, 898 insertions(+), 1 deletion(-) create mode 100644 self-hosting/README.md create mode 100644 self-hosting/bypass-cgnat/README.md create mode 100644 self-hosting/bypass-cgnat/backup/wireguard-config/wg0-local.conf create mode 100644 self-hosting/bypass-cgnat/backup/wireguard-config/wg0-server.conf create mode 100644 self-hosting/bypass-cgnat/iptables/iptables-down.sh create mode 100644 self-hosting/bypass-cgnat/iptables/iptables-up.sh create mode 100644 self-hosting/bypass-cgnat/local.sh create mode 100644 self-hosting/bypass-cgnat/server.sh create mode 100644 self-hosting/services/ejabberd/README.md create mode 100644 self-hosting/services/examplereverseproxy.conf create mode 100644 self-hosting/services/examplewebsite.conf create mode 100644 self-hosting/services/nextcloud/README.md create mode 100644 self-hosting/services/nextcloud/nextcloud.conf create mode 100644 self-hosting/services/onlyoffice/README.md create mode 100644 system_administration/secure-ssh/README.md rename {wireless-network-debian => system_administration/wireless-network-debian}/README.md (98%) diff --git a/self-hosting/README.md b/self-hosting/README.md new file mode 100644 index 0000000..7b87629 --- /dev/null +++ b/self-hosting/README.md @@ -0,0 +1,23 @@ +# self-hosted + +## Description +Aims to be a comprehensible guide to a self-hosted, FOSS digital presence. + +## Roadmap +- Fininsh scripting the Bypass CGNAT part. +- Script the deployment of common apps for reproducibility. + +## Authors and acknowledgment + +I used these sources as a guide, documented steps and added useful configurations. + +[mochman@github](https://github.com/mochman) - [Bypass CGNAT](https://github.com/mochman/Bypass_CGNAT) + +[nerdonthestreet@github](https://github.com/nerdonthestreet) - [Install ONLYOFFICE on a Nextcloud Server](https://www.youtube.com/watch?v=Gc1zUmrxtKE) + +[DenshiVideo](https://wiki.denshi.org/hypha/server/ejabberd) - [How to setup an XMPP server (ejabberd)](https://www.youtube.com/watch?v=rY0kRSj2rmU) + +[Matthew Evan](https://github.com/MattMadness) - [landchad.net/nextcloud](https://landchad.net/nextcloud/) + +## Project status +Very early stages, doesn't work, use as a guide for manual implementation. diff --git a/self-hosting/bypass-cgnat/README.md b/self-hosting/bypass-cgnat/README.md new file mode 100644 index 0000000..5e406f3 --- /dev/null +++ b/self-hosting/bypass-cgnat/README.md @@ -0,0 +1,3 @@ +# Bypass CGNAT +Setup a wireguard VPN to route traffic from a VPS to your local machine. +Based from [this](https://github.com/mochman/Bypass_CGNAT) guide. diff --git a/self-hosting/bypass-cgnat/backup/wireguard-config/wg0-local.conf b/self-hosting/bypass-cgnat/backup/wireguard-config/wg0-local.conf new file mode 100644 index 0000000..f8ce86d --- /dev/null +++ b/self-hosting/bypass-cgnat/backup/wireguard-config/wg0-local.conf @@ -0,0 +1,7 @@ +Address = 10.0.0.2 + +[Peer] +PublicKey = PUBLICKEY +AllowedIPs = 10.0.0.1/32 +Endpoint = VPSIP:55107 +PersistentKeepalive = 25 diff --git a/self-hosting/bypass-cgnat/backup/wireguard-config/wg0-server.conf b/self-hosting/bypass-cgnat/backup/wireguard-config/wg0-server.conf new file mode 100644 index 0000000..e8f0385 --- /dev/null +++ b/self-hosting/bypass-cgnat/backup/wireguard-config/wg0-server.conf @@ -0,0 +1,6 @@ +ListenPort = 55107 +Address = 10.0.0.1/24 + +[Peer] +PublicKey = PUBLICKEY +AllowedIPs = 10.0.0.2/32 diff --git a/self-hosting/bypass-cgnat/iptables/iptables-down.sh b/self-hosting/bypass-cgnat/iptables/iptables-down.sh new file mode 100644 index 0000000..eeedfee --- /dev/null +++ b/self-hosting/bypass-cgnat/iptables/iptables-down.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +VPSINT="enp1s0" + +TCP=$(cat /opt/wireguard/ports-tcp.txt) +: "${tcpports:=$TCP}" +for port in $tcpports; do + iptables -D FORWARD -i "$VPSINT" -o wg0 -p tcp --syn --dport "$port" -m conntrack --ctstate NEW -j ACCEPT + iptables -t nat -D PREROUTING -i "$VPSINT" -p tcp --dport "$port" -j DNAT --to-destination 10.0.0.2 + iptables -t nat -D POSTROUTING -o wg0 -p tcp --dport "$port" -d 10.0.0.2 -j SNAT --to-source 10.0.0.1 + ufw deny "$port"/tcp +done + +UDP=$(cat /opt/wireguard/ports-udp.txt) +: "${udpports:=$UDP}" +for port in $udpports; do + iptables -D FORWARD -i "$VPSINT" -o wg0 -p udp --dport "$port" -m conntrack --ctstate NEW -j ACCEPT + iptables -t nat -D PREROUTING -i "$VPSINT" -p udp --dport "$port" -j DNAT --to-destination 10.0.0.2 + iptables -t nat -D POSTROUTING -o wg0 -p udp --dport "$port" -d 10.0.0.2 -j SNAT --to-source 10.0.0.1 + ufw deny "$port"/udp +done + diff --git a/self-hosting/bypass-cgnat/iptables/iptables-up.sh b/self-hosting/bypass-cgnat/iptables/iptables-up.sh new file mode 100644 index 0000000..6e38a70 --- /dev/null +++ b/self-hosting/bypass-cgnat/iptables/iptables-up.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +VPSINT="INTERFACE" + +TCP=$(cat /opt/wireguard/ports-tcp.txt) +: "${tcpports:=$TCP}" +for port in $tcpports; do + iptables -A FORWARD -i "$VPSINT" -o wg0 -p tcp --syn --dport "$port" -m conntrack --ctstate NEW -j ACCEPT + iptables -t nat -A PREROUTING -i "$VPSINT" -p tcp --dport "$port" -j DNAT --to-destination 10.0.0.2 + iptables -t nat -A POSTROUTING -o wg0 -p tcp --dport "$port" -d 10.0.0.2 -j SNAT --to-source 10.0.0.1 + ufw allow "$port"/tcp +done + +UDP=$(cat /opt/wireguard/ports-udp.txt) +: "${udpports:=$UDP}" +for port in $udpports; do + iptables -A FORWARD -i "$VPSINT" -o wg0 -p udp --dport "$port" -m conntrack --ctstate NEW -j ACCEPT + iptables -t nat -A PREROUTING -i "$VPSINT" -p udp --dport "$port" -j DNAT --to-destination 10.0.0.2 + iptables -t nat -A POSTROUTING -o wg0 -p udp --dport "$port" -d 10.0.0.2 -j SNAT --to-source 10.0.0.1 + ufw allow "$port"/udp +done + diff --git a/self-hosting/bypass-cgnat/local.sh b/self-hosting/bypass-cgnat/local.sh new file mode 100644 index 0000000..35b205b --- /dev/null +++ b/self-hosting/bypass-cgnat/local.sh @@ -0,0 +1,43 @@ +#!/bin/sh +# Local utility for forwarding traffic through wireguard VPN +# +# Some code was borrowed from: +# https://github.com/mochman/Bypass_CGNAT +# and +# https://www.youtube.com/watch?v=9tDeh9mutmI +perms=$(umask) + +print() { + printf '\033[1m %b\033[0m%s\n\n' "$1" +} + +# Install wireguard +printf "\nContinue ONLY is wireguard is installed [y/N] " && read -r check +[ "$check" != "y" ] && exit + +# Generate wireguard keys +print "Generating wireguard configs..." +sudo mkdir -p /etc/wireguard/ +umask 077 # perms for /etc/wireguard/* files +printf "[Interface]\nPrivateKey = " | sudo tee /etc/wireguard/wg0.conf > /dev/null +printf "\nCopy this key to server's setup (Press ENTER when done):\n> " +sudo wg genkey | sudo tee -a /etc/wireguard/wg0.conf | wg pubkey | sudo tee /etc/wireguard/publickey +read -r NULL + +# Make wireguard configuration with keys and write to /etc/wireguard/wg0.conf +printf "\nEnter the generated Publickey from server:\n> " && read -r PUBKEY +printf "\nEnter the VPS's public IP:\n> " && read -r VPSIP +printf "Address = 10.0.0.2 + +[Peer] +PublicKey = $PUBKEY +AllowedIPs = 10.0.0.1/32 +Endpoint = $VPSIP:55107 +PersistentKeepalive = 25 +" | sudo tee -a /etc/wireguard/wg0.conf +umask $perms # restore perms + +# Start service +#sudo systemctl start wg-quick@wg0 +printf "\nRun 'systemctl enable wg-quick@wg0' so the service starts automatically on boot.\n" +printf "\nDone!\n" diff --git a/self-hosting/bypass-cgnat/server.sh b/self-hosting/bypass-cgnat/server.sh new file mode 100644 index 0000000..626c721 --- /dev/null +++ b/self-hosting/bypass-cgnat/server.sh @@ -0,0 +1,64 @@ +#!/bin/sh +# Server utility for forwarding traffic through wireguard VPN +# +# Some code was borrowed from: +# https://github.com/mochman/Bypass_CGNAT +# and +# https://www.youtube.com/watch?v=9tDeh9mutmI +perms=$(umask) + +print() { + printf '\033[1m %b\033[0m%s\n\n' "$1" +} + +# Enable forwarding FIX +print "Enabling ip_forward..." +cat /etc/sysctl.conf | sed "s/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/g" | sudo tee /etc/sysctl.conf +sudo sysctl -p +sudo sysctl --system + +# Install wireguard +print "Installing wireguard..." +sudo apt-get install wireguard -y # Install wireguard +ip a + +# Prompt for required fields +printf "\nEnter the VPS's public IP interface (see with 'ip a'):\n> " && read -r VPSINT + +# Generate keys and write configuration to /etc/wireguard/wg0.conf +print "Generating wireguard configs..." +sudo mkdir -p /etc/wireguard/ +umask 077 # perms for /etc/wireguard/* files +printf "[Interface]\nPrivateKey = " | sudo tee /etc/wireguard/wg0.conf > /dev/null +sudo wg genkey | sudo tee -a /etc/wireguard/wg0.conf | wg pubkey | sudo tee /etc/wireguard/publickey +printf "\nEnter the generated /etc/wireguard/publickey from local machine:\n> " && read -r PUBKEY +printf "ListenPort = 55107 +Address = 10.0.0.1/24 + +PostUp = /opt/wireguard/iptables-up.sh +PostDown = /opt/wireguard/iptables-down.sh + +[Peer] +PublicKey = $PUBKEY +AllowedIPs = 10.0.0.2/32 +" | sudo tee -a /etc/wireguard/wg0.conf +printf "\nCopy this key to local machine's setup:\n> " +sudo cat /etc/wireguard/publickey +read -r NULL +umask $perms # restore perms + +# Start service +print "Starting wg-quick@wg0..." +sudo ufw allow 55107 +sudo systemctl start wg-quick@wg0 + +# iptables configuration +print "Configuring iptables & ufw..." +sudo iptables -P FORWARD DROP +sudo iptables -A FORWARD -i "$VPSINT" -o wg0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT +sudo iptables -A FORWARD -i wg0 -o "$VPSINT" -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT + +sudo ufw status | grep -q "active" && sudo ufw reload + +print "\nDone!\n" +printf "Run 'systemctl enable wg-quick@wg0' so the service starts automatically on boot.\n\n" diff --git a/self-hosting/services/ejabberd/README.md b/self-hosting/services/ejabberd/README.md new file mode 100644 index 0000000..2df43af --- /dev/null +++ b/self-hosting/services/ejabberd/README.md @@ -0,0 +1,149 @@ +# Enable ports + +These are the ports needed for ejabberd to work. +Ports 80 and 443 are needed for deploying and SSL certificate with certbot. + +```shell +declare -a ports=("80" "443" "5222:5443/udp" "5222:5443/tcp" "3478" "49152:65535/udp" "49152:65535/tcp") + +for port in "${ports[@]}"; do ufw allow "$port" ; done +ufw reload +``` + +# Download ejabberd + +Debian conveniently offers the packages in the official repositories! + +```shell +apt update +apt install ejabberd python3-certbot-nginx +systemctl enable --now ejabberd +``` + +# Generate certs + +This is from [Nerd on the Street](https://github.com/nerdonthestreet). +Change the DOMAIN variable to your preference. + +```shell +DOMAIN="example.org" + +# Set the domain names you want here, stun & turn are required for calls +declare -a subdomains=("" "conference." "proxy." "pubsub." "upload." "stun." "turn.") + +for i in "${subdomains[@]}"; do + certbot --nginx -d $i$DOMAIN certonly + mkdir -p /etc/ejabberd/certs/$i$DOMAIN + cp /etc/letsencrypt/live/$i$DOMAIN/fullchain.pem /etc/ejabberd/certs/$i$DOMAIN + cp /etc/letsencrypt/live/$i$DOMAIN/privkey.pem /etc/ejabberd/certs/$i$DOMAIN +done +``` + +# Directories and permissions + +```shell +chown -R ejabberd:ejabberd /etc/ejabberd/certs +mkdir -p /var/www/upload +chown -R ejabberd:ejabberd /var/www/upload +``` + +# Base configuration + +Fill with your domain. + +```yaml +hosts: + - example.org +``` + +Enable the path for previously generated certs. + +```yaml +certfiles: + - "/etc/ejabberd/certs/*/*.pem" +``` + +Note: Remember to `systemctl restart ejabberd` each time you modify `/etc/ejabberd.yml`. + +# Example for some configs (optional) + +## Admin user + +Register admin user. + +```shell +su -c "ejabberdctl register admin example.org ADMIN_PASSWORD" ejabberd +systemctl restart ejabberd +``` + +Enable admin user. + +```yaml +acl: + admin: + user: admin +``` + +## Message archive and http upload + +Uncomment for compliance with XMPP standards. + +```yaml +mod_http_upload: + put_url: https://@HOST@:5443/upload + docroot: /var/www/upload + custom_headers: + "Access-Control-Allow-Origin": "https://@HOST@" + "Access-Control-Allow-Methods": "GET,HEAD,PUT,OPTIONS" + "Access-Control-Allow-Headers": "Content-Type" +``` + +Enable message archive. + +```yaml +mod_mam: + assume_mam_usage: true + default: always +``` + +## Postgresql database + +Set postgresql as database. + +```shell +sudo -i -u postgres psql -c "CREATE USER ejabberd WITH PASSWORD 'DB_PASSWORD';" +sudo -i -u postgres psql -c "CREATE DATABASE ejabberd OWNER ejabberd;" +``` + +```yaml +sql_type: pgsql +sql_server: "localhost" +sql_database: "ejabberd" +sql_username: "ejabberd" +sql_password: "DB_PASSWORD" +default_db: sql +``` + +## Call/Videocall support + +Enable this module + +```yaml +ejabberd_stun: +``` + +## Registration + +Enable registration in your server + +```yaml +mod_register: +``` + +Otherwise registered via: + +```shell +su -c "ejabberdctl register USERNAME example.org USER_PASSWORD" ejabberd +``` + +Note: Remember to `systemctl restart ejabberd` each time you modify `/etc/ejabberd.yml`. diff --git a/self-hosting/services/examplereverseproxy.conf b/self-hosting/services/examplereverseproxy.conf new file mode 100644 index 0000000..e7d854d --- /dev/null +++ b/self-hosting/services/examplereverseproxy.conf @@ -0,0 +1,12 @@ +server { + + listen 80; + listen [::]:80; + + server_name example.domain.xyz; + + location / { + proxy_pass http://localhost:8080/; + } + +} diff --git a/self-hosting/services/examplewebsite.conf b/self-hosting/services/examplewebsite.conf new file mode 100644 index 0000000..31b71df --- /dev/null +++ b/self-hosting/services/examplewebsite.conf @@ -0,0 +1,22 @@ +server { + + listen 80; + listen [::]:80; + + server_name example.domain.xyz; + + root /var/www/examplesite; + + # Add index.php to the list if you are using PHP + index index.html; + + location / { + try_files $uri $uri/ =404; + } + + #location ~ \.php$ { + # include snippets/fastcgi-php.conf; + # fastcgi_pass unix:/run/php/php7.4-fpm.sock; + #} + +} diff --git a/self-hosting/services/nextcloud/README.md b/self-hosting/services/nextcloud/README.md new file mode 100644 index 0000000..25587d6 --- /dev/null +++ b/self-hosting/services/nextcloud/README.md @@ -0,0 +1,235 @@ +# Ask for domain & database credentials +printf "Domain name (e.g. cloud.example.com):\n * DNS records must already be set up!\n> " && read -r domain +printf "nextcloud database admin username:\n> " && read -r nextcloud_db_admin +printf "nextcloud database admin password:\n> " && read -r nextcloud_db_admin_pass + +# Install dependencies + +```shell +apt install -y curl nginx python3-certbot-nginx postgresql php php-{fpm,bcmath,bz2,intl,gd,mbstring,pgsql,zip,xml,curl,imagick,gmp} +``` + +For some reason that installs apache2, remove it as we don't need it. + +```shell +apt purge apache2 +apt autoremove +``` + +### Check PHP version... + +As of 2023-07-10, it's 8.2. +You can also check with `ls /etc/php` by checking the version's folder name. + +```shell +php -v | grep -o '[0-9].*(cli)' | cut -d '.' -f 1,2 +``` + +# Set up postgresql database + +```shell +systemctl enable --now postgresql +sudo -i -u postgres psql -c "CREATE USER nextcloud WITH PASSWORD 'DB_PASSWORD';" +sudo -i -u postgres psql -c "CREATE DATABASE nextcloud TEMPLATE template0 ENCODING 'UTF8';" +sudo -i -u postgres psql -c "ALTER DATABASE nextcloud OWNER TO nextcloud;" +sudo -i -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE nextcloud TO nextcloud;" +sudo -i -u postgres psql -c "GRANT ALL PRIVILEGES ON SCHEMA public TO nextcloud;" +``` + +# Nginx configuration & cert +I modified this config to be easily set up with SSL via certbot, +but you can visit the following url for the official example: +[Nextcloud's nginx example configuration](https://docs.nextcloud.com/server/19/admin_manual/installation/nginx.html). +```shell +curl -L nextcloud-nginx.tavo.one | sed "s/cloud.example.com/YOURDOMAIN/g" | tee /etc/nginx/sites-available/nextcloud.conf +ln -s /etc/nginx/sites-available/nextcloud.conf /etc/nginx/sites-enabled/ +systemctl restart nginx +certbot -d YOURDOMAIN --nginx --register-unsafely-without-email --agree-tos +``` + +# Download & extract latest nextcloud +```shell +wget -O /opt/nextcloud-$(date -I).tar.bz2 https://download.nextcloud.com/server/releases/latest.tar.bz2 +tar -xjf /opt/nextcloud-$(date -I).tar.bz2 -C /var/www +``` + +# Permissions for www-data user & restart services +```shell +chown -R www-data:www-data /var/www/nextcloud +chmod -R 755 /var/www/nextcloud +systemctl enable --now php8.2-fpm +systemctl enable --now nginx +``` + +# Recommended modifications: + +RECOMMENDED MODIFICATIONS TO ENHANCE +SECURITY & PERFORMANCE: + +I find it better to configure them +one by one and troubleshoot each one +separately that way! + +## Tune php-fpm + +Recommended settings for `/etc/php/8.2/fpm/pool.d/www.conf` +This should get rid of the _'getenv("PATH") only returns an empty response'_ +overview panel notification, plus enhance performance. + +```php +pm = dynamic +pm.max_children = 120 +pm.start_servers = 12 +pm.min_spare_servers = 6 +pm.max_spare_servers = 18 + +env[HOSTNAME] = $HOSTNAME +env[PATH] = /usr/local/bin:/usr/bin:/bin +env[TMP] = /tmp +env[TMPDIR] = /tmp +env[TEMP] = /tmp +``` + +Recommended settings for `/etc/php/$php_ver/fpm/php.ini` +Sometimes when installing apps, an error might occur +and it's not always verbose as to why it can't proceed. +This could fix some of those problems. + +```php +opcache.interned_strings_buffer=32 + +memory_limit = 512M +``` + +## Tune memcache + +### APCu local memcache +For performance, documentation suggests enabling a +memcache, for 'local memcache', APCu is recommended. + +Install dependencies + +```shell +apt install php-apcu +``` + +Add the following lines to `/var/www/nextcloud/config/config.php` under `$CONFIG=array`... + +```php +'memcache.local' => '\OC\Memcache\APCu', +``` + +In order to avoid problems with cron jobs, +Nextcloud's docs suggest to add these +somewhere in `php.ini`, but I found it +worked best when I added them in +`/etc/php/$php_ver/mods-available/apcu.ini` +(extension=apcu.so should already be there): + +```php +extension=apcu.so +apc.enabled=1 +apc.enable_cli=1 +``` + +Restart php$php_ver-fpm +```shell +systemctl restart php8.2-fpm +``` + +### Redis server (Transactional file locking) +This is enabled by default in nextcloud to prevent +dataloss with failed uploads or disconnects, however, +it loads your database greatly for this purpose. +To delegate this processing to redis, docs recommend: + +NOTE: +If you run into trouble just remove the +`memcache.locking' => '\OC\Memcache\Redis'`, +line mentioned below. + +Insall required pacakges + +```shell +apt install redis-server php-redis +``` + +Uncomment & modify `/etc/redis/redis.conf` + +``` +port 0 +unixsocket /run/redis/redis.sock +unixsocketperm 770 +``` + +Permissions, enable & run redis + +```shell +sudo usermod -a -G redis www-data +systemctl enable --now redis-server +``` + +Add the following lines to `/var/www/nextcloud/config/config.php` under `$CONFIG=array`... + +```php +'filelocking.enabled' => true, +'memcache.locking' => '\OC\Memcache\Redis', +'redis' => array( + 'host' => '/var/run/redis/redis.sock', + 'port' => 0, + 'timeout' => 0.0, + ), +``` + + +(Optional) For distributed cache, also add: +`memcache.distributed' => '\OC\Memcache\Redis'`, + +Similarly with APCu, it is recommended +to add these settings in php.ini, I just +find it cleaner in the respective module's +config in `/etc/php/$php_ver/mods-available/redis.ini` +(extension=redis.so should already be there): + +```php +extension=redis.so +redis.session.locking_enabled=1 +redis.session.lock_retries=-1 +redis.session.lock_wait_time=10000 +``` + +```shell +Restart services +systemctl restart redis-server +systemctl restart php$php_ver-fpm +systemctl restart nginx +``` + +## Cron for background jobs + +Run the following command: + +```shell +crontab -u www-data -e +``` + +Append the following line AS IS +to the end of the document +(as recommended in nextcloud docs): + +``` +*/5 * * * * php -f /var/www/nextcloud/cron.php +``` + +```shell +systemctl restart php8.2-fpm +``` + +## Apply +If applied, restart to apply changes with: + +```shell +systemctl restart redis-server +systemctl restart php$php_ver-fpm +systemctl restart nginx +``` diff --git a/self-hosting/services/nextcloud/nextcloud.conf b/self-hosting/services/nextcloud/nextcloud.conf new file mode 100644 index 0000000..6451a90 --- /dev/null +++ b/self-hosting/services/nextcloud/nextcloud.conf @@ -0,0 +1,166 @@ +upstream php-handler { + #server 127.0.0.1:9000; + server unix:/run/php/php8.2-fpm.sock; +} + +# Set the `immutable` cache control options only for assets with a cache busting `v` argument +map $arg_v $asset_immutable { + "" ""; + default "immutable"; +} + + +server { + listen 80; + listen [::]:80; + server_name cloud.example.com; + + # Prevent nginx HTTP Server Detection + server_tokens off; + + # Path to the root of your installation + root /var/www/nextcloud; + + # set max upload size and increase upload timeout: + client_max_body_size 512M; + client_body_timeout 300s; + fastcgi_buffers 64 4K; + + # Enable gzip but do not remove ETag headers + gzip on; + gzip_vary on; + gzip_comp_level 4; + gzip_min_length 256; + gzip_proxied expired no-cache no-store private no_last_modified no_etag auth; + gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy; + + # The settings allows you to optimize the HTTP2 bandwitdth. + # See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/ + # for tunning hints + client_body_buffer_size 512k; + + # HTTP response headers borrowed from Nextcloud `.htaccess` + add_header Referrer-Policy "no-referrer" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-Download-Options "noopen" always; + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Permitted-Cross-Domain-Policies "none" always; + add_header X-Robots-Tag "noindex, nofollow" always; + add_header X-XSS-Protection "1; mode=block" always; + + # Remove X-Powered-By, which is an information leak + fastcgi_hide_header X-Powered-By; + + # Add .mjs as a file extension for javascript + # Either include it in the default mime.types list + # or include you can include that list explicitly and add the file extension + # only for Nextcloud like below: + include mime.types; + types { + text/javascript js mjs; + } + + # Specify how to handle directories -- specifying `/index.php$request_uri` + # here as the fallback means that Nginx always exhibits the desired behaviour + # when a client requests a path that corresponds to a directory that exists + # on the server. In particular, if that directory contains an index.php file, + # that file is correctly served; if it doesn't, then the request is passed to + # the front-end controller. This consistent behaviour means that we don't need + # to specify custom rules for certain paths (e.g. images and other assets, + # `/updater`, `/ocm-provider`, `/ocs-provider`), and thus + # `try_files $uri $uri/ /index.php$request_uri` + # always provides the desired behaviour. + index index.php index.html /index.php$request_uri; + + # Rule borrowed from `.htaccess` to handle Microsoft DAV clients + location = / { + if ( $http_user_agent ~ ^DavClnt ) { + return 302 /remote.php/webdav/$is_args$args; + } + } + + location = /robots.txt { + allow all; + log_not_found off; + access_log off; + } + + # Make a regex exception for `/.well-known` so that clients can still + # access it despite the existence of the regex rule + # `location ~ /(\.|autotest|...)` which would otherwise handle requests + # for `/.well-known`. + location ^~ /.well-known { + # The rules in this block are an adaptation of the rules + # in `.htaccess` that concern `/.well-known`. + + location = /.well-known/carddav { return 301 /remote.php/dav/; } + location = /.well-known/caldav { return 301 /remote.php/dav/; } + + location /.well-known/acme-challenge { try_files $uri $uri/ =404; } + location /.well-known/pki-validation { try_files $uri $uri/ =404; } + + # Let Nextcloud's API for `/.well-known` URIs handle all other + # requests by passing them to the front-end controller. + return 301 /index.php$request_uri; + } + + # Rules borrowed from `.htaccess` to hide certain paths from clients + location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/) { return 404; } + location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console) { return 404; } + + # Ensure this block, which passes PHP files to the PHP process, is above the blocks + # which handle static assets (as seen below). If this block is not declared first, + # then Nginx will encounter an infinite rewriting loop when it prepends `/index.php` + # to the URI, resulting in a HTTP 500 error response. + location ~ \.php(?:$|/) { + # Required for legacy support + rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+|.+\/richdocumentscode\/proxy) /index.php$request_uri; + + fastcgi_split_path_info ^(.+?\.php)(/.*)$; + set $path_info $fastcgi_path_info; + + try_files $fastcgi_script_name =404; + + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param PATH_INFO $path_info; + fastcgi_param HTTPS on; + + fastcgi_param modHeadersAvailable true; # Avoid sending the security headers twice + fastcgi_param front_controller_active true; # Enable pretty urls + fastcgi_pass php-handler; + + fastcgi_intercept_errors on; + fastcgi_request_buffering off; + + fastcgi_max_temp_file_size 0; + } + + # Serve static files + location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map)$ { + try_files $uri /index.php$request_uri; + add_header Cache-Control "public, max-age=15778463, $asset_immutable"; + access_log off; # Optional: Don't log access to assets + + location ~ \.wasm$ { + default_type application/wasm; + } + } + + location ~ \.woff2?$ { + try_files $uri /index.php$request_uri; + expires 7d; # Cache-Control policy borrowed from `.htaccess` + access_log off; # Optional: Don't log access to assets + } + + # Rule borrowed from `.htaccess` + location /remote { + return 301 /remote.php$request_uri; + } + + location / { + try_files $uri $uri/ /index.php$request_uri; + } + +} + diff --git a/self-hosting/services/onlyoffice/README.md b/self-hosting/services/onlyoffice/README.md new file mode 100644 index 0000000..bd0bffa --- /dev/null +++ b/self-hosting/services/onlyoffice/README.md @@ -0,0 +1,43 @@ +# Add non-free and contrib + +Edit `/etc/apt/sources.list` and make sure to have enabled **non-free** and **contrib**. + +``` +deb http://deb.debian.org/debian/ bookworm main non-free-firmware non-free contrib +``` + +# Install dependencies +```shell +apt install -y nginx nginx-extras postgresql rabbitmq-server redis gnupg libcurl4 libxml2 fonts-dejavu fonts-liberation ttf-mscorefonts-installer fonts-crosextra-carlito fonts-takao-gothic fonts-opensymbol +``` + +# OnlyOffice configuration +```shell +echo onlyoffice-documentserver onlyoffice/ds-port select 81 | sudo debconf-set-selections +sudo -i -u postgres psql -c "CREATE USER onlyoffice WITH PASSWORD 'DB_PASSWORD';" +sudo -i -u postgres psql -c "CREATE DATABASE onlyoffice OWNER onlyoffice;" +``` + +# OnlyOffice Docs repository +```shell +mkdir -p -m 700 ~/.gnupg +curl -fsSL https://download.onlyoffice.com/GPG-KEY-ONLYOFFICE | gpg --no-default-keyring --keyring gnupg-ring:/tmp/onlyoffice.gpg --import +chmod 644 /tmp/onlyoffice.gpg +chown root:root /tmp/onlyoffice.gpg +mv /tmp/onlyoffice.gpg /usr/share/keyrings/onlyoffice.gpg + +echo "deb [signed-by=/usr/share/keyrings/onlyoffice.gpg] https://download.onlyoffice.com/repo/debian squeeze main" | sudo tee /etc/apt/sources.list.d/onlyoffice.list +apt-get update + +apt install onlyoffice-documentserver # Will ask for DB_PASSWORD +``` + +# Nginx reverse proxy & HTTPS + +```shell +curl -L reverse-proxy.tavo.one | sed "s/example.domain.xyz/YOURDOMAIN/g" | tee /etc/nginx/sites-available/onlyoffice.conf +ln -s /etc/nginx/sites-available/onlyoffice.conf /etc/nginx/sites-enabled/ + +systemctl restart nginx +certbot -d YOURDOMAIN --nginx --register-unsafely-without-email --agree-tos +``` diff --git a/system_administration/secure-ssh/README.md b/system_administration/secure-ssh/README.md new file mode 100644 index 0000000..252b0b5 --- /dev/null +++ b/system_administration/secure-ssh/README.md @@ -0,0 +1,80 @@ +# First login + +```shell +# Login into the VPS +ssh root@codespec.xyz + +# Update packages +apt update && apt upgrade + +# Enable automatic updates +apt install unattended-upgrades +dpkg-reconfigure unattended-upgrades +``` + +# Add a new user + +This is done so that you can disable +loging in as root user. + +```shell +# '-m' creates a home directory, +# '-s' assigns a shell (/bin/bash in this case), +# 'user' is the name you want to give it +useradd -m -s /bin/bash user +passwd user # Set a password for 'user' +``` + +Add 'user' to sudo group. This will allow to execute +commands as root, such as `sudo apt update`. +Some distros user 'wheel' group instead of 'sudo' +Run command `visudo` to check root enabled groups. +Debian, Ubuntu and derivatives usually use 'sudo'. + +```shell +usermod -aG sudo user # Give 'user' sudo privileges +su - user # Login into 'user' +sudo apt update # Test that you have access to sudo + +# Exit your server, you may need to run 'exit' twice. +exit +``` + +# Configure SSH keypair + +## In your local machine: +```shell +ssh-keygen # Generate keypair +ssh-copy-id -i ~/.ssh/id_rsa.pub user@codespec.xyz # Copy to server +ssh user@codespec.xyz # Check it works +``` + +## ONCE IN THE VPS: +`sudo nano /etc/ssh/sshd_config` +Make sure to configure as follows +(We only need to allow 'user', but +you can add multiple users as well): + +```ssh +PermitRootLogin no +AllowUsers user otheruser yetanotheruser +PasswordAuthentication no +UsePam no +``` + +Then, restart SSH daemon + +```shell +systemctl restart sshd +``` + +# Enable UFW + +```shell +# Allow SSH before enabling, +# Will drop shell otherwise. +ufw allow 22 + +# Enable firewall +ufw enable +``` diff --git a/wireless-network-debian/README.md b/system_administration/wireless-network-debian/README.md similarity index 98% rename from wireless-network-debian/README.md rename to system_administration/wireless-network-debian/README.md index 6e11b60..b80f948 100644 --- a/wireless-network-debian/README.md +++ b/system_administration/wireless-network-debian/README.md @@ -118,7 +118,7 @@ Which then can be appended to the `/etc/wpa_supplicant/wpa_supplicant.conf` file **Note**: The `#psk=` line can be omitted for the hashed password. However, this will not prevent others with access to this hash to connect to the network, but at least it will not reveal the -plain text password. +plain text password if the system is compromised. **Note**: Make sure this file is not readable by running: