Modern setup for selfhosted services

2026-08-28
#howto #ubuntu #server #selfhosted #docker

§ Intro

In this note I’ll document my homelab setup on one cloud VPS with docker-compose. I’m finally happy with the result.

For homelab I use:

  • Glance as a home dashboard
  • Gitea: git to store code, configuration, etc
  • Vaultwarden: password manager
  • Memos: small notes I use as public “twitter”
  • Miniflux: rss aggregator
  • Outline: wiki to store notes and documentation, neat integration with drawio
  • 3x-ui and wireguard for “corporate” network

The full docker-compose collection is available in repo: https://git.ksar.dev/bikulov/ksar

I’d like to outline some features:

  1. only proxy (Traefik) exposes web ports
  2. services with two+ containers are isolated by networks: for example, miniflux has no network access to outline-db
  3. variables in .env files, example for each service provided
  4. each service is a separate folder. You may use only traefik and gitea: just run them

Where needed, services are configured to support SSO and to be connected to gitea as SSO provider.

Below are some details about chosen settings.

restart: unless-stopped - all containers restarted after Docker daemon reload (if they are not stopped manually).

I use folders to store data:

volumes:
      - ./data/gitea:/data

§ traefik

  • --api.insecure=false – disable the insecure API and dashboard: necessary for prod
  • --providers.docker=true – configure traefik for Docker
  • --providers.docker.exposedbydefault=false – do not add all containers to traefik, only those explicitly marked with traefik.enable=true
  • --providers.docker.network=proxy – what network to use in Docker to choose the IP for service

These three lines are for HTTP -> HTTPS redirect:

  • --entryPoints.web.address=:80
  • --entryPoints.web.http.redirections.entryPoint.to=websecure
  • --entryPoints.web.http.redirections.entryPoint.scheme=https

Settings for automatic letsencrypt:

  • --entryPoints.websecure.address=:443
  • --certificatesresolvers.le.acme.tlschallenge=true
  • --certificatesresolvers.le.acme.email=${TRAEFIK_MAIL}
  • --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json

And the only labels needed for containers are:

  • traefik.enable=true
  • traefik.http.services.<CONTAINER_NAME>.loadbalancer.server.port=<APP_PORT>
  • traefik.http.routers.<CONTAINER_NAME>.rule=Host(${SERVER_HOST})
  • traefik.http.routers.<CONTAINER_NAME>.entrypoints=websecure
  • traefik.http.routers.<CONTAINER_NAME>.tls.certresolver=le

§ Deploy order

There is some dependencies: all services use SSO for login. But at first time it is not configured. So:

  1. Start with traefik
  2. Then gitea as SSO provider
  3. … then any of the supported services …
  4. Configure glance to monitor all services and start it

Happy homelabing!