Name |
URL |
Description |
Access to internet |
Caddy |
bookmarks.${BASE_DOMAIN} |
Web server and reverse proxy |
Yes |
Immich |
photos.${BASE_DOMAIN} |
Photo and video backup solution |
No |
Obsidian LiveSync |
obsidian.${BASE_DOMAIN} |
Community-implemented synchronization plugin |
No |
Pi-hole |
pihole.${BASE_DOMAIN} |
DNS server |
Yes |
Technitium |
technitium.${BASE_DOMAIN} |
DNS server |
Yes |
Radicale |
contacts.${BASE_DOMAIN} |
CardDAV (contact) server |
No |
Syncthing |
syncthing.${BASE_DOMAIN} |
Continuous File Synchronization |
Yes |
Vaultwarden |
vault.${BASE_DOMAIN} |
Unofficial Bitwarden compatible server |
No |
- Create DNS entries in Cloudflare, pointing to Wireguard's internal address
- Set env vars (see below)
- Go through setup.sh
- Configure and enable WireGuard
sudo systemctl enable --now wg-quick@wg0
- Start containers:
docker compose -f ${DATA_PATH}/caddy/docker/docker-compose.yml build --pull --no-cache
docker compose -f ${DATA_PATH}/radicale/docker/docker-compose.yml build --pull --no-cache
docker compose -f ${DATA_PATH}/syncthing/docker/docker-compose.yml pull
docker compose -f ${DATA_PATH}/vaultwarden/docker/docker-compose.yml pull
docker compose -f ${DATA_PATH}/immich/docker/docker-compose.yml pull
docker compose -f ${DATA_PATH}/technitium/docker/docker-compose.yml pull
docker compose -f ${DATA_PATH}/caddy/docker/docker-compose.yml up --force-recreate -d
docker compose -f ${DATA_PATH}/radicale/docker/docker-compose.yml up --force-recreate -d
docker compose -f ${DATA_PATH}/syncthing/docker/docker-compose.yml up --force-recreate -d
docker compose -f ${DATA_PATH}/vaultwarden/docker/docker-compose.yml up --force-recreate -d
docker compose -f ${DATA_PATH}/immich/docker/docker-compose.yml up --force-recreate -d
docker compose -f ${DATA_PATH}/technitium/docker/docker-compose.yml up --force-recreate -d
- Create borg repo (if not created yet):
borg init --encryption=none /backup/containers
${DATA_PATH}/${SERVICE}/docker: Dockerfile / docker-compose.yml / config.env
${DATA_PATH}/${SERVICE}/configs: service configurations
${DATA_PATH}/${SERVICE}/volumes: persistent data created by the services
export BASE_DOMAIN=domain.com
export DATA_PATH=/data/containers
export BACKUP_PATH=/backup/containers
export CADDY_PASSWORD=$(openssl rand -hex 48)
export CADDY_HASHED_PASSWORD=$(docker run caddy:2-alpine caddy hash-password --plaintext ${CADDY_PASSWORD})
export CADDY_CLOUDFLARE_TOKEN=taken from Cloudflare
export IMMICH_DATABASE_PASSWORD=$(openssl rand -hex 48)
export IMMICH_JWT_SECRET=$(openssl rand -hex 48)
export OBSIDIAN_COUCHDB_PASSWORD=$(openssl rand -hex 48)
export PIHOLE_ADMIN_TOKEN=$(openssl rand -hex 48)
export PIHOLE_WEBPASSWORD=$(openssl rand -hex 48)
export TECHNITIUM_ADMIN_PASSWORD=$(openssl rand -hex 48)
export RADICALE_PASSWORD=$(openssl rand -hex 48)
export RADICALE_USER_PASSWORD=$(htpasswd -n -b admin ${RADICALE_PASSWORD})
export VAULTWARDEN_ADMIN_TOKEN=$(openssl rand -hex 48)
export CADDY_HASHED_PASSWORD=
export CADDY_CLOUDFLARE_TOKEN=
export IMMICH_DATABASE_PASSWORD=
export IMMICH_JWT_SECRET=
export OBSIDIAN_COUCHDB_PASSWORD=
export PIHOLE_ADMIN_TOKEN=
export PIHOLE_WEBPASSWORD=
export TECHNITIUM_ADMIN_PASSWORD=
export RADICALE_USER_PASSWORD=
export VAULTWARDEN_ADMIN_TOKEN=
# Update system
apt update
apt full-upgrade -y
apt autoremove -y
# Update containers
# docker compose -f ${DATA_PATH}/technitium/docker/docker-compose.yml pull
docker compose -f ${DATA_PATH}/caddy/docker/docker-compose.yml build --pull --no-cache
docker compose -f ${DATA_PATH}/radicale/docker/docker-compose.yml build --pull --no-cache
docker compose -f ${DATA_PATH}/pihole/docker/docker-compose.yml build --pull --no-cache
docker compose -f ${DATA_PATH}/syncthing/docker/docker-compose.yml pull
docker compose -f ${DATA_PATH}/vaultwarden/docker/docker-compose.yml pull
docker compose -f ${DATA_PATH}/immich/docker/docker-compose.yml pull
# Shutdown containers
# docker compose -f ${DATA_PATH}/technitium/docker/docker-compose.yml down
docker compose -f ${DATA_PATH}/caddy/docker/docker-compose.yml down
docker compose -f ${DATA_PATH}/radicale/docker/docker-compose.yml down
docker compose -f ${DATA_PATH}/pihole/docker/docker-compose.yml down
docker compose -f ${DATA_PATH}/syncthing/docker/docker-compose.yml down
docker compose -f ${DATA_PATH}/vaultwarden/docker/docker-compose.yml down
docker compose -f ${DATA_PATH}/immich/docker/docker-compose.yml down
# Backup containers data
borg create /backup/containers::{now:%Y-%m-%d} ${DATA_PATH}
borg prune --keep-weekly=4 --keep-monthly=3 ${BACKUP_PATH}
# Start containers
# docker compose -f ${DATA_PATH}/technitium/docker/docker-compose.yml up --force-recreate -d
docker compose -f ${DATA_PATH}/caddy/docker/docker-compose.yml up --force-recreate -d
docker compose -f ${DATA_PATH}/radicale/docker/docker-compose.yml up --force-recreate -d
docker compose -f ${DATA_PATH}/pihole/docker/docker-compose.yml up --force-recreate -d
docker compose -f ${DATA_PATH}/syncthing/docker/docker-compose.yml up --force-recreate -d
docker compose -f ${DATA_PATH}/vaultwarden/docker/docker-compose.yml up --force-recreate -d
docker compose -f ${DATA_PATH}/immich/docker/docker-compose.yml up --force-recreate -d
# Clear docker data
docker system prune -af
docker compose -f ${DATA_PATH}/caddy/docker/docker-compose.yml down
docker compose -f ${DATA_PATH}/radicale/docker/docker-compose.yml down
docker compose -f ${DATA_PATH}/syncthing/docker/docker-compose.yml down
docker compose -f ${DATA_PATH}/vaultwarden/docker/docker-compose.yml down
docker compose -f ${DATA_PATH}/immich/docker/docker-compose.yml down
docker compose -f ${DATA_PATH}/technitium/docker/docker-compose.yml down
- Restore volumes to correct directories
- Start only postgres:
docker compose -f ${DATA_PATH}/immich/docker/docker-compose.yml up -d immich-postgres
- Start the rest of the containers:
docker compose -f ${DATA_PATH}/immich/docker/docker-compose.yml up -d
# Delete old partition layout and re-read partition table
sudo wipefs -af /dev/sda
sudo sgdisk --zap-all --clear /dev/sda
sudo partprobe /dev/sda
# Partition disk and re-read partition table
sudo sgdisk -n 1:0:0 -t 1:8300 /dev/sda
sudo partprobe /dev/sda
# Format partition to EXT4
sudo mkfs.ext4 /dev/sda1
# Mount
sudo mkdir -p /data
sudo mount -t ext4 /dev/sda1 /data
# Auto-mount
sudo tee -a /etc/fstab << EOF
# data disk
UUID=$(lsblk -n -o UUID /dev/sda1) /data ext4 defaults 0 0
EOF
# Change ownership to user
sudo chown -R $USER:$USER /data
# Delete old partition layout and re-read partition table
sudo wipefs -af /dev/sdb
sudo sgdisk --zap-all --clear /dev/sdb
sudo partprobe /dev/sdb
# Partition disk and re-read partition table
sudo sgdisk -n 1:0:0 -t 1:8300 /dev/sdb
sudo partprobe /dev/sdb
# Format partition to EXT4
sudo mkfs.ext4 /dev/sdb1
# Mount
sudo mkdir -p /backup
sudo mount -t ext4 /dev/sdb1 /backup
# Auto-mount
sudo tee -a /etc/fstab << EOF
# backup disk
UUID=$(lsblk -n -o UUID /dev/sdb1) /backup ext4 defaults 0 0
EOF
# Change ownership to user
sudo chown -R $USER:$USER /backup