Alpine Linux Musl += (btrfs + gummiboot) >> Eventually Installation: { # setup-alpine: >> Will be replaced eventually with manual install with btrfs and gummiboot, instead of default ext4 and grub. { \ } # reboot $ doas vim /etc/apk/repositories: { > {v3.15/main} > {v3.15/community} > {edge/main} > {edge/community} > {edge/testing} } } Post install: { # apk add git # git clone https://git.bijl.us/luc/alpine-server.git ups(client): { # apk add nut build-base # gcc alpine-server/config-files/ups.c -o /bin/ups # gcc alpine-server/config-files/exec-ups.c -o /bin/exec-ups # vim /etc/init.d/ups: { > #!/sbin/openrc-run > name="ups" > command="/bin/exec-ups" } # rc-update add ups # rc-service ups start } acf: { # apk add acf $ setup-acf # vim /etc/mini_httpd/mini_httpd.conf: { > port=444 } } rsnapshot: << May be substituted with duplicati! { # apk add rsnapshot # cp /etc/rsnapshot.conf.default /etc/rsnapshot.conf # vim /etc/rsnapshot.conf: { > snapshot_root /media/data/backup > retain daily 7 > retain weekly 4 > retain monthly 12 > backup /home/ localhost/ > backup /etc/ localhost/ > backup /usr/local/ /localhost > backup /opt/ /localhost > backup /var/lib/docker/ /localhost } # vim /etc/periodic/{*}/rsnapshot: { > #!/bin/sh > exec /usr/bin/rsnapshot {*} } # chmod +x /etc/periodic/{*}/rsnapshot # rc-update add crond # rc-service crond start } apk-autoupdate : << Does not work possibly. { # apk add apk-autoupdate # vim /etc/periodic/weekly/apk-autoupdate: { > #!/bin/sh > exec /usr/sbin/apk-autoupdate } } Samba: { # apk add samba # vim /etc/samba/samba.conf: { > [global] > allow insecure wide links = yes > dos charset = cp866 > unix charset = utf-8 > workgroup = WORKGROUP > server string = Samba Server > [home{user}] > comment = homedir{user} > valid_users = {user} > path = /home/{user} > browseable = yes > writable = yes } # rc-update add samba # rc-service samba start } ssh: { # apk add openssh fail2ban # rc-update add sshd # rc-service sshd start # rc-update add fail2ban # rc-service fail2ban start } Docker: { # apk add docker docker-compose # addgroup docker # rc-update add docker boot # service docker start portainer: { # cp alpine-server/config-files/portainer.yml /opt/docker-compose.yml $ cd /opt/ $ docker-compose up -d } traefik: { + Add stack << traefik.yml } watchtower: { Image: containerrr/watchtower:latest Volumes: { /etc/localtime:/etc/localtime:ro /var/run/docker.sock:/var/run/docker.sock } Network: bridge Environment: { WATCHTOWER_NOTIFICATION_EMAIL_FROM = info@{domain} WATCHTOWER_NOTIFICATION_EMAIL_TO=user@{domain} WATCHTOWER_NOTIFICATION_EMAIL_SERVER=mail.{domain} WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PORT=465 WATCHTOWER_NOTIFICATION_EMAIL_SERVER_USER=info WATCHTOWER_NOTIFICATION_EMAIL_SERVER_PASSWORD={passwd} WATCHTOWER_NOTIFICATION_EMAIL_DELAY=2 WATCHTOWER_NOTIFICATIONS=email WATCHTOWER_SCHEDULE=0 0 0 * * 6 WATCHTOWER_CLEANUP=true WATCHTOWER_DEBUG=true } Restart: Unless-stopped } duplicati: { Image: ghcr.io/linuxserver/duplicati:latest Ports: 8200:8200/tcp Volumes: { /backups:/var/backups /source:duplicati-source - local /config:/opt/duplicati /source/host_home:/home:ro /source/host_etc:/etc:ro /source/host_opt:/opt:ro /source/host_usr_local:/usr/local:ro } Network: bridge Environment: { PIUD=0 PGID=0 TZ=Europe/Amsterdam } Restart: Unless-stopped } webserver: { Image: httpd:latest Volumes: { /usr/local/apache2/htdocs /opt/{webserver}/html } Network: proxy Labels: << traefik.labels Restart: Unless-stopped } postgres: { Image: postgres:latest Volumes: { /backup:/opt/postgres /etc/localtime:/etc/localtime:ro /var/lib/postgresql/data:postgres - local } Network: proxy Environment: { POSTGRES_PASSWORD={passwd} PGDATA=/var/lib/postgresql/data } Labels: com.centurylinklabs.watchtower.monitor-only: "true" Restart: Unless-stopped Manual backup database: { $ docker exec -it postgres sh -c "pg_dump -U postgres -d {database} |gzip /backup/{database}.gz" } Manual reload database: { $ # docker exec -it postgres sh -c "gunzip -c {dbname.gz} | psql -U postgres -d {dbname}" } } postgresbackup: { Image: prodrigestivill/postgres-backup-local:latest Volumes: { /backups:/opt/postgresbackup /var/lib/postgresql/data:postgresbackup - local /etc/localtime:/etc/localtime:ro } Network: proxy Environment: { POSTGRES_HOST=postgres POSTGRES_DB={db0,db1,...,db{n}} POSTGRES_USER=postgres SCHEDULE=@daily BACKUP_KEEP_DAYS=1 BACKUP_KEEP_WEEKS=1 BACKUP_KEEP_MONTHS=1 BACKUP_DIR=/backups } Labels: com.centurylinklabs.watchtower.monitor-only: "true" Restart: Unless-stopped Reload database: { # mv /opt/postgresbackup/{dbname.sql.gz} /opt/postgres $ docker exec -it postgres sh -c "zcat /backup/{dbname.sql.gz} | psql -U postgres -d {dbname}" } } vaultwarden: { $ docker exec -it postgres /bin/bash # psql -U postgres: { > create database vaultwarden; } Image: vaultwarden/server:latest Volumes: { /data:/opt/vaultwarden/data /etc/localtime:/etc/localtime:ro } Network: proxy Environment: { ADMIN_TOKEN={admin_token} >> Remove to disable admin page. SIGNUPS_ALLOWED=true/false DATABASE_URL=postgresql://postgres:{passwd}@postgres/vaultwarden } Labels: << traefik.labels Restart: Unless-stopped } gitea: { $ docker exec -it postgres /bin/bash # psql -U postgres: { > create database gitea; } Image: gitea/gitea:latest Volumes: { /data:/opt/gitea /etc/localtime:/etc/localtime:ro /etc/timezone:/etc/timezone:ro } Network: proxy Environment: { USER_UID=1000 USER_GID=1000 GITEA__database__DB_TYPE=postgres GITEA__database__HOST=postgres GITEA__database__NAME=gitea GITEA__database__USER=postgres GITEA__database__PASSWD={passwd} USER=git GITEA_CUSTOM=/data/gitea } Labels: << traefik.labels Restart: Unless-stopped } } matrix: { synapse: { $ docker exec -it postgres /bin/bash # psql -U postgres: { > create database synapse with encoding='UTF8' lc_collate='C' lc_ctype='C' template=template0; } $ docker run -it --rm --mount type=volume,src=synapse-data,dst=/data -e SYNAPSE_SERVER_NAME=matrix.{domain} -e SYNAPSE_REPORT_STATS=no matrixdotorg/synapse:latest generate $ docker run -d --name synapse --mount type=volume,src=synapse-data,dst=/data matrixdotorg/synapse:latest >> May be improved! Network: proxy Labels: << traefik.labels Restart: Unless-stopped # vim /var/lib/docker/volumes/synapse-data/_data/homeserver.yaml: { > server_name: "matrix.{domain}" > database: > name: psycopg2 > txn_limit: 10000 > allow_unsafe_locale: false > args: > user: postgres > password: "{passwd}" > database: synapse > host: postgres > cp_min: 5 > cp_max: 10 > enable_registration: true/false > enable_registration_without_verification: true > app_server_config_files: > - /data/mautrix/whatsapp/registration.yaml > - /data/mautrix/signal/registration.yaml } } mautrix-whatsapp: { $ docker exec -it postgres /bin/bash # psql -U postgres: { > create database mautrixwhatsapp; } Image: dock.mau.dev/mautrix/whatsapp:latest Volumes: { /data:/var/lib/docker/volumes/synapse-data/_data/mautrix/whatsapp /etc/localtime:/etc/localtime:ro } Network: proxy Restart: Unless-stopped # vim /var/lib/docker/volumes/synapse-data/_data/mautrix/whatsapp/config.yaml: { > homeserver: > address: http://synapse:8008 > domain: matrix.{domain} > appservice: > address: http://mautrix-whatsapp:29318 > hostname: 0.0.0.0 > port: 29318 > > database: > type: postgres > uri: postgres://postgres:{passwd}@postgres/mautrixwhatsapp?sslmode=disable > bridge: > private_chat_portal_meta: true > encryption: > allow: true > default: true > > permissions: > "*": relay > "matrix.{domain}": user > "@admin:matrix.{domain}": admin } # vim /var/lib/docker/volumes/synapse-data/_data/mautrix/whatsapp/registration.yaml: { > url: http://mautrix-whatsapp:29318 > regex: << matrix.{domain} } } mautrix-signal: { $ docker exec -it postgres /bin/bash # psql -U postgres: { > create database mautrixsignal; } Image: dock.mau.dev/mautrix/signal:latest Volumes: { /data:/var/lib/docker/volumes/synapse-data/_data/mautrix/signal /etc/localtime:/etc/localtime:ro } Network: proxy Restart: Unless-stopped # vim /var/lib/docker/volumes/synapse-data/_data/mautrix/whatsapp/config.yaml: { > homeserver: > address: http://synapse:8008 > domain: matrix.{domain} > appservice: > address: http://mautrix-signal:29328 > hostname: 0.0.0.0 > port: 29328 > > database: postgres://postgres:{passwd}@postgres/mautrixsignal > signal: > socket_path: /data/signald/signald.sock > bridge: > private_chat_portal_meta: true > encryption: > allow: true > default: true > > permissions: > "*": relay > "matrix.{domain}": user > "@admin:matrix.{domain}: admin } # vim /var/lib/docker/volumes/synapse-data/_data/mautrix/whatsapp/registration.yaml: { > url: http://mautrix-signal:29328 > regex: << matrix.{domain} } } signald: { >> postgres database not yet available! (sqlite database) Image:docker.io/signald/signald:latest Volumes: { /signald:/opt/matrix/mautrix-signal/signald /etc/localtime:/etc/localtime:ro } Network: proxy Restart: Unless-stopped } element: { Image: vectorim/element-web:latest Volumes: { /app/config.json:/opt/matrix/element/config.json /etc/localtime:/etc/localtime:ro } Network: proxy Labels: << traefik.labels Restart: Unless-stopped # vim /opt/matrix/element/config.json: { { "default_server_config": { "m.homeserver": { "base_url": "https://matrix.{domain}", "server_name": "matrix.{domain}" }, "m.identity_server": { "base_url": "https://vector.im" } }, "disable_custom_urls": true, "room_directory": { "servers": ["matrix.org", "matrix.{domain}"] }, "default_theme": "dark" } } } } homeassistant: { mosquitto: { Image: eclipse-mosquitto:latest Volumes: { /mosquitto/data:/opt/mosquitto/data /mosquitto/log:/opt/mosquitto/log /mosquitto/config:/opt/mosquitto/config } Network: { proxy ipv4: 172.21.0.12 } Restart: Unless-stopped # vim /opt/mosquitto/config/password.txt: { > {username}:{passwd} } # vim /opt/mosquitto/config/mosquitto.conf: { > persistence true > persistence_location /mosquitto/data > log_dest file /mosquitto/log/mosquitto.log > listener 9001 > listener 1883 > connection_messages true > allow_anonymous false > password_file /mosquitto/config/password.txt } } ecowitt: { Image: bachya/ecowitt2mqtt:latest Ports: 8181:8181/tcp Network: proxy Environment: { COWITT2MQTT_MQTT_BROKER=mosquitto ECOWITT2MQTT_MQTT_USERNAME={username} ECOWITT2MQTT_MQTT_PASSWORD={passwd} ECOWITT2MQTT_PORT=8181 ECOWITT2MQTT_HASS_DISCOVERY=true ECOWITT2MQTT_INPUT_UNIT_SYSTEM=imperial ECOWITT2MQTT_OUTPUT_UNIT_SYSTEM=metric } Restart: Unless-stopped } esphome: { Image: esphome/esphome:latest Ports: 6052:6052/tcp Volumes: { /config:/opt/esphome /etc/localtime:/etc/localtime:ro } Network: host Environment: { USERNAME={username} PASSWORD={passwd} } Restart: Unless-stopped } homeassistant: { $ docker exec -it postgres /bin/bash # psql -U postgres: { > create database homeassistant; } Image: homeassistant Volumes: { /config:/opt/homeassistant/config /etc/localtime:/etc/localtime:ro } Network: proxy Labels: << traefik.labels Restart: Unless-stopped # vim /opt/homeassistant/config/configuration.yaml: { > python_script: > shell_command: > http: > use_x_forwarded_for: true > trusted_proxies: > - 172.21.0.80 > panel_iframe: > portainer: > title: "Portainer" > url: "http://{ip}:9000/#/containers" > icon: mdi:docker > require_admin: true > esphome: > title: "ESPHome" > url: "http://{ip}:6052" > icon: mdi:chip > require_admin: true > recorder: > db_url: postgresql://postgres:{passwd}@postgres/homeassistant } } } }