Initial commit
This commit is contained in:
135
README.md
Normal file
135
README.md
Normal 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 / Let’s 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
5
duckdns/duck.log
Normal 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
19
duckdns/duck.sh
Executable 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
41
homelab/Caddyfile
Normal 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
55
homelab/compose.yml
Normal 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
|
||||||
Reference in New Issue
Block a user