Initial commit

This commit is contained in:
2025-11-15 14:30:39 +02:00
commit bb50bd75af
5 changed files with 255 additions and 0 deletions

135
README.md Normal file
View File

@@ -0,0 +1,135 @@
# Homelab Setup (Vaultwarden + 2FAuth + Caddy + DuckDNS)
This repository contains the configuration for my personal homelab stack, including:
- **Vaultwarden** self-hosted password manager (Bitwarden-compatible)
- **2FAuth** self-hosted two-factor authentication manager
- **Caddy** reverse proxy with automatic HTTPS via DuckDNS (DNS-01)
- **DuckDNS Updater** updates my dynamic IP address automatically
The setup is built with Docker Compose and is designed to be simple, secure, and easy to maintain.
## Directory Structure
```bash
.
├── duckdns
│ ├── duck.log # Log file for DuckDNS updates
│ └── duck.sh # DuckDNS update script (runs via cron)
└── homelab
├── Caddyfile # Reverse proxy configuration for Caddy
└── compose.yml # Docker Compose stack for Vaultwarden + 2FAuth + Caddy
```
## Secrets and Environment Variables
Before deploying, you **must** replace all placeholder values in the config files.
- `https://vault.example.com` and `vault.example.com` → your Vaultwarden domain
- `https://auth.example.com` and `auth.example.com` → your 2FAuth domain
- `admin@example.com` → your email address (used by Caddy / Lets Encrypt and 2FAuth)
- `TOKEN` → your DuckDNS token
- `SomeRandomStringOf32CharsExactly` → a **32-character** random string for `APP_KEY`
## DuckDNS Dynamic DNS Updater
The `duckdns/duck.sh` script updates all DuckDNS domains used by the homelab. It always logs to `duckdns/duck.log`.
### Run manually
```bash
cd duckdns
./duck.sh
```
### Cron to run periodically (recommended)
```bash
cd duckdns
chmod 700 duck.sh
crontab -e
```
Add:
```bash
*/5 * * * * /path/to/duckdns/duck.sh >/dev/null 2>&1
```
This ensures your DuckDNS domains always point to your current IP.
## Homelab Stack (Docker Compose)
The **homelab/** folder contains:
- `compose.yml` runs Vaultwarden, 2FAuth, and Caddy
- `Caddyfile` defines routing for:
- `https://<vault-domain>` → Vaultwarden
- `https://<auth-domain>` → 2FAuth
### Start the stack
```bash
cd homelab
docker compose up -d
```
### Stop the stack
```bash
cd homelab
docker compose down
```
### View logs
```bash
docker logs caddy -f
docker logs vaultwarden -f
docker logs 2fauth -f
```
### Auto-start on system boot
The containers already use:
```yml
restart: always
```
But remember to enable Docker on startup:
```bash
sudo systemctl enable docker
```
### Set correct permissions for volumes (optional)
Run:
```bash
sudo chown -R 1000:1000 homelab/vaultwarden
sudo chmod -R 755 homelab/vaultwarden
sudo chown -R 1000:1000 homelab/2fauth
sudo chmod -R 755 homelab/2fauth
```
Then restart the containers:
```bash
cd homelab
docker compose restart vaultwarden 2fauth
```
## Updating
To update to the latest versions:
```bash
cd homelab
docker compose pull
docker compose up -d
```
This will refresh all Docker images with zero downtime.

5
duckdns/duck.log Normal file
View File

@@ -0,0 +1,5 @@
OKUpdating DuckDNS domain andy-auth:
OK
Updating DuckDNS domain andy-vault:
OK
DuckDNS update completed at Sat Nov 15 02:05:38 PM EET 2025

19
duckdns/duck.sh Executable file
View File

@@ -0,0 +1,19 @@
#!/bin/bash
# === CONFIGURATION ===
TOKEN="TOKEN"
DOMAINS=("auth" "vault")
LOG_DIR="$(cd "$(dirname "$0")" && pwd)"
LOG_FILE="$LOG_DIR/duck.log"
# === SETUP ===
mkdir -p "$LOG_DIR"
# === UPDATE ALL DOMAINS ===
for domain in "${DOMAINS[@]}"; do
echo "Updating DuckDNS domain $domain:" >> "$LOG_FILE"
curl -ks "https://www.duckdns.org/update?domains=${domain}&token=${TOKEN}&ip=" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
done
echo "DuckDNS update completed at $(date)" >> "$LOG_FILE"

41
homelab/Caddyfile Normal file
View File

@@ -0,0 +1,41 @@
# ===========================
# Vaultwarden
# ===========================
{$VAULT_DOMAIN} {
log {
level INFO
output file {$LOG_FILE} {
roll_size 10MB
roll_keep 10
}
}
tls {
dns duckdns {$DUCKDNS_TOKEN}
}
encode zstd gzip
reverse_proxy vaultwarden:80
}
# ===========================
# 2FAuth
# ===========================
{$AUTH_DOMAIN} {
log {
level INFO
output file {$LOG_FILE} {
roll_size 10MB
roll_keep 10
}
}
tls {
dns duckdns {$DUCKDNS_TOKEN}
}
encode zstd gzip
reverse_proxy 2fauth:8000
}

55
homelab/compose.yml Normal file
View File

@@ -0,0 +1,55 @@
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: always
volumes:
- ./vaultwarden:/data
environment:
DOMAIN: "https://vault.example.com" # Change to yours
2fauth:
image: 2fauth/2fauth:latest
container_name: 2fauth
restart: always
volumes:
- ./2fauth:/data
environment:
- APP_NAME=2FAuth
- APP_ENV=production
- APP_DEBUG=false
- APP_TIMEZONE=Europe/Helsinki
- SITE_OWNER=admin@example.com # Change to yours
- APP_KEY=SomeRandomStringOf32CharsExactly # Change to yours
- APP_URL=https://auth.example.com # Change to yours
- ASSET_URL=https://auth.example.com # Change to yours
- TRUSTED_PROXIES=*
- LOG_CHANNEL=daily
- LOG_LEVEL=notice
networks:
- default
caddy:
image: caddy:2
container_name: caddy
restart: always
ports:
- 80:80
- 443:443
- 443:443/udp
volumes:
- ./caddy:/usr/bin/caddy
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- ./caddy-config:/config
- ./caddy-data:/data
environment:
# For Caddy: hostnames only, no https://
VAULT_DOMAIN: "vault.example.com" # Change to yours
AUTH_DOMAIN: "auth.example.com" # Change to yours
EMAIL: "admin@example.com" # Change to yours
DUCKDNS_TOKEN: "TOKEN" # Change to yours
LOG_FILE: "/data/access.log"
networks:
default:
driver: bridge