kert f958c374c6
All checks were successful
ci/woodpecker/push/build Pipeline was successful
Disable deploy step to prevent CI self-destruction
2026-02-05 18:32:06 -05:00
2026-02-04 19:51:32 -05:00

Homelab Stack

Self-hosted infrastructure stack with GPU support, S3-compatible storage, Git server with container registry, CI/CD, and research tools.

Services

Service URL Description
Gitea http://gitea.home.fhirworx.io:3000 Git server with LFS + container registry
Woodpecker CI http://ci.home.fhirworx.io:8000 CI/CD pipelines
RustFS http://s3.home.fhirworx.io:9000 S3-compatible object storage
RustFS Console http://s3.home.fhirworx.io:9001 Storage management UI
Notebooks http://notebooks.home.fhirworx.io:2718 GPU-accelerated Jupyter
Zotero http://zotero.home.fhirworx.io:8080 Reference manager with VNC
PostgreSQL localhost:5432 Database (Bitnami hardened)

Prerequisites

  • Docker with rootless mode
  • NVIDIA GPU with container toolkit
  • Fix for rootless NVIDIA containers:
    sudo sed -i 's/#no-cgroups = false/no-cgroups = true/' /etc/nvidia-container-runtime/config.toml
    

DNS Setup

Add to /etc/hosts (replace with your server's LAN IP):

cat << 'EOF' | sudo tee -a /etc/hosts

# homelab stack
192.168.1.192 gitea.home.fhirworx.io
192.168.1.192 ci.home.fhirworx.io
192.168.1.192 s3.home.fhirworx.io
192.168.1.192 notebooks.home.fhirworx.io
192.168.1.192 zotero.home.fhirworx.io
EOF

Or configure these records on your router/DNS server.

Setup

1. Environment Variables

Create .env file:

POSTGRES_PASSWORD=<your_password>
RUSTFS_ACCESS_KEY=<your_access_key>
RUSTFS_SECRET_KEY=<your_secret_key>
GITEA_S3_ACCESS_KEY=<gitea_s3_user>
GITEA_S3_SECRET_KEY=<gitea_s3_password>
GITEA_DB_PASSWORD=<gitea_db_password>
GITEA_TOKEN=<gitea_api_token>
WOODPECKER_DB_PASSWORD=<woodpecker_db_password>
WOODPECKER_AGENT_SECRET=<generated_secret>
WOODPECKER_GITEA_CLIENT=<oauth_client_id>
WOODPECKER_GITEA_SECRET=<oauth_client_secret>

Generate agent secret:

openssl rand -hex 32

2. Start Core Services

docker compose up -d postgres rustfs

3. Configure RustFS

  1. Access console at http://s3.home.fhirworx.io:9001
  2. Create user git with S3 credentials matching GITEA_S3_ACCESS_KEY and GITEA_S3_SECRET_KEY
  3. Create buckets: gitea, gitea-lfs, gitea-packages
  4. Apply IAM policy to git user:
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetBucketLocation",
        "s3:ListBucket",
        "s3:ListBucketMultipartUploads"
      ],
      "Resource": [
        "arn:aws:s3:::gitea",
        "arn:aws:s3:::gitea-lfs",
        "arn:aws:s3:::gitea-packages"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject",
        "s3:ListMultipartUploadParts",
        "s3:AbortMultipartUpload"
      ],
      "Resource": [
        "arn:aws:s3:::gitea/*",
        "arn:aws:s3:::gitea-lfs/*",
        "arn:aws:s3:::gitea-packages/*"
      ]
    }
  ]
}

4. Configure PostgreSQL

Create databases and users:

# Gitea database
docker exec -e PGPASSWORD=<postgres_password> postgres psql -U postgres -c "CREATE DATABASE gitea;"
docker exec -e PGPASSWORD=<postgres_password> postgres psql -U postgres -c "CREATE USER git WITH PASSWORD '<gitea_db_password>'; ALTER DATABASE gitea OWNER TO git;"

# Woodpecker database
docker exec -e PGPASSWORD=<postgres_password> postgres psql -U postgres -c "CREATE DATABASE woodpecker;"
docker exec -e PGPASSWORD=<postgres_password> postgres psql -U postgres -c "CREATE USER woodpecker WITH PASSWORD '<woodpecker_db_password>'; ALTER DATABASE woodpecker OWNER TO woodpecker;"

5. Start Gitea

docker compose up -d gitea

6. Configure Gitea

  1. Complete initial setup at http://gitea.home.fhirworx.io:3000
  2. Create organization homelab
  3. Create repository stack
  4. Generate API token for container registry access
  5. Create OAuth2 application for Woodpecker:
    • Name: Woodpecker CI
    • Redirect URI: http://ci.home.fhirworx.io:8000/authorize
    • Copy Client ID and Secret to .env

7. Start Woodpecker CI

docker compose up -d woodpecker-server woodpecker-agent

Add secrets in Woodpecker UI (http://ci.home.fhirworx.io:8000):

  • registry_user - Gitea username
  • registry_pass - Gitea token

8. SSH and GPG Keys

Generate SSH key:

ssh-keygen -t ed25519 -C "user@homelab" -f ~/.ssh/gitea_ed25519 -N ""

Generate GPG key:

gpg --batch --gen-key <<EOF
Key-Type: eddsa
Key-Curve: ed25519
Key-Usage: sign
Subkey-Type: ecdh
Subkey-Curve: cv25519
Subkey-Usage: encrypt
Name-Real: <your_name>
Name-Email: <your_email>
Expire-Date: 2y
%no-protection
%commit
EOF

Configure Git:

git config --global user.name "<your_name>"
git config --global user.email "<your_email>"
git config --global user.signingkey <GPG_KEY_ID>
git config --global commit.gpgsign true

Add to ~/.ssh/config:

Host gitea
    HostName gitea.home.fhirworx.io
    Port 2222
    User git
    IdentityFile ~/.ssh/gitea_ed25519
    IdentitiesOnly yes

Add host key:

ssh-keyscan -p 2222 gitea.home.fhirworx.io >> ~/.ssh/known_hosts

Add SSH and GPG public keys to Gitea: http://gitea.home.fhirworx.io:3000/user/settings/keys

9. Deploy Key (for CI/CD)

ssh-keygen -t ed25519 -C "deploy@homelab/stack" -f .deploy_key -N ""

Add .deploy_key.pub to repository deploy keys: http://gitea.home.fhirworx.io:3000/homelab/stack/settings/keys

10. Push to Gitea

git remote add gitea gitea:homelab/stack.git
git push -u gitea main

11. Container Registry

Login:

echo "<GITEA_TOKEN>" | docker login localhost:3000 -u <username> --password-stdin

Tag and push images:

docker tag <image>:latest localhost:3000/homelab/<image>:latest
docker push localhost:3000/homelab/<image>:latest

12. Start All Services

docker compose up -d

Container Registry Images

All images are hosted in the Gitea container registry:

  • localhost:3000/homelab/postgresql:latest
  • localhost:3000/homelab/rustfs:latest
  • localhost:3000/homelab/gitea:latest-rootless
  • localhost:3000/homelab/woodpecker-server:latest
  • localhost:3000/homelab/woodpecker-agent:latest
  • localhost:3000/homelab/notebooks:latest
  • localhost:3000/homelab/zotero:latest

CI/CD Pipeline

The .woodpecker.yml pipeline:

  1. validate - Validates docker compose config
  2. build-notebooks - Builds notebooks image (on changes to notebooks/)
  3. build-zotero - Builds zotero image (on changes to zotero/)
  4. push-images - Pushes to container registry (on main branch)
  5. deploy - Pulls and restarts services (on main branch)

Endpoints

Service URL
Gitea Web http://gitea.home.fhirworx.io:3000
Gitea SSH ssh://git@gitea.home.fhirworx.io:2222
Container Registry http://gitea.home.fhirworx.io:3000/v2/
Woodpecker CI http://ci.home.fhirworx.io:8000
RustFS S3 API http://s3.home.fhirworx.io:9000
RustFS Console http://s3.home.fhirworx.io:9001
PostgreSQL localhost:5432
Notebooks http://notebooks.home.fhirworx.io:2718
Zotero http://zotero.home.fhirworx.io:8080
Description
No description provided
Readme 4.9 GiB
Languages
Python 94.5%
HTML 2.8%
CSS 1.3%
Go 0.5%
Shell 0.3%
Other 0.6%