Post

This Hits A Little Close To Home For Some Of Us

This Hits A Little Close To Home For Some Of Us

This Hits A Little Close To Home For Some Of Us

Why Documentation And Ticket Tracking Still Matter In A Self‑Hosted World

If you’ve ever stared at a cluttered terminal, opened a stack of half‑finished notes, or felt that uneasy pang when a ticket sits untouched for days, you’re not alone. The Reddit thread that sparked this conversation laid bare a universal truth: even in the most automated, self‑hosted environments, the human need to prove “I did something” persists.

For homelab enthusiasts, DevOps engineers, and seasoned sysadmins, the challenge isn’t just keeping services up and running. It’s also about making the invisible work visible, proving value, and protecting yourself from the “I‑don’t‑remember‑what‑I‑did‑last‑week” trap. This guide tackles that exact pain point. You’ll learn how to build a lightweight, yet powerful, ticket‑tracking and documentation workflow that integrates cleanly with the tools you already run in your self‑hosted stack.

By the end of this post you will:

  • Understand why traditional ticketing systems still matter for infrastructure work.
  • Choose the right open‑source tools that fit a homelab or small‑scale production environment.
  • Follow a step‑by‑step installation and configuration process that avoids common pitfalls.
  • Apply best‑practice hardening, performance, and scaling tips for long‑term reliability.
  • Troubleshoot the most frequent issues without resorting to endless log‑scrolling.

All of this is presented for an audience that already knows the basics of Docker, systemd, and basic networking, but wants a more structured way to track, document, and prove their infrastructure efforts.


Understanding The Topic

What Are We Actually Talking About?

At its core, the discussion revolves around work‑tracking and documentation for infrastructure automation. This includes:

  • Ticket creation and status management for tasks like “upgrade PostgreSQL”, “migrate backups”, or “refactor Docker Compose network”.
  • Markdown‑based notes stored alongside code repositories, ensuring that every change is accompanied by a rationale.
  • Automation hooks that automatically log actions (e.g., a GitLab CI job that updates a ticket when a PR merges).

The technology stack that supports this workflow can be as simple as a Kanban board in GitHub Projects or as robust as a full‑featured open‑source issue tracker like YouTrack or Taiga. For most homelab owners, the sweet spot lies in lightweight, self‑hosted solutions that can be containerized and integrated with existing services.

A Brief History

The concept of “ticketing” originated in software development labs where engineers needed a way to track bugs, feature requests, and operational tasks. Early systems like Bugzilla (1996) and later JIRA (2004) introduced databases, workflows, and customizable fields.

In the DevOps era, the rise of Infrastructure as Code (IaC) and GitOps shifted the focus from isolated bug trackers to holistic work management that lives alongside code. Tools such as GitHub Issues, GitLab Issues, and Phabricator now provide APIs that let you tie a commit, a deployment, or a container restart to a specific ticket number.

For self‑hosted environments, the last decade has seen a surge of open‑source, self‑contained ticket systems that can run on a single VM or inside Docker containers. Projects like Wekan, Gitea’s Issue Tracker, and Redmine offer varying degrees of customization, but the most common denominator is the need for clear documentation that proves you’ve done the work.

Key Features And Capabilities

A solid ticket‑tracking system for infrastructure should provide:

  1. Issue Lifecycle Management – From “Opened” to “In Progress” to “Closed”, with customizable statuses.
  2. Linking To Code – Ability to reference commits, branches, or container images directly from an issue.
  3. Automation Hooks – Webhooks or APIs that trigger scripts (e.g., a post‑deployment script that marks a ticket as resolved).
  4. Rich Text Documentation – Markdown support for detailed, version‑controlled notes.
  5. Search And Tagging – Quickly locate tickets by label, project, or keyword.

These capabilities address the exact concerns raised in the Reddit thread: “How else am I supposed to document that I’ve done something?” and “Look if you documented a rare, unique, or unsolved issue you deserve the self medal.”

Pros And Cons

AdvantageExplanation
Self‑hosted controlYou own the data, can enforce security policies, and avoid vendor lock‑in.
Integration with CI/CDNative webhooks let you automatically close tickets when a deployment succeeds.
Version‑controlled notesMarkdown files stored in Git ensure that every change is auditable.
Community supportOpen‑source projects often have active forums, Docker images, and extensive docs.
DrawbackMitigation
Initial setup overheadUse pre‑built Docker images and follow a documented installation script.
Learning curve for workflow customizationStart with a minimal configuration, then iterate based on real‑world usage.
Resource consumptionRun the tracker in a lightweight container; monitor CPU and memory with docker stats.

Real‑World Applications

  • Homelab Backup Automation – A ticket tracks “Weekly encrypted backup of Nextcloud”. When the cron job finishes, a webhook updates the ticket status to “Completed”.
  • Network Refactor – Updating VLAN configurations across multiple Proxmox nodes is logged as a ticket with step‑by‑step Markdown instructions stored in the repo.
  • Service Migration – Migrating a legacy web service from Docker Compose to Kubernetes is broken into sub‑tasks, each with its own ticket and linked PR.

These scenarios illustrate why documenting the “what” and the “why” is as critical as the technical execution itself.


Prerequisites

Before you dive into installation, verify that your environment meets the following baseline requirements.

System Requirements

ComponentMinimum VersionReason
CPU2 coresNeeded for container orchestration and ticket processing.
RAM2 GBSufficient for Docker Engine and the ticketing container.
Disk20 GB freeHolds images, logs, and persistent data.
OSUbuntu 22.04 LTS (or Debian 12)Well‑supported packages and long‑term security updates.

Required Software

SoftwareVersionInstallation Command
Docker Engine24.0+curl -fsSL https://get.docker.com | sh && sudo usermod -aG docker $USER
Docker Compose2.24+sudo apt-get install -y docker-compose-plugin
Git2.34+sudo apt-get install -y git
SQLite (for lightweight DB)3.39+sudo apt-get install -y sqlite3

Network And Security

  • Port 8080 (or another free port) must be open for the web UI.
  • Firewall – Allow inbound traffic on the chosen port and restrict access to trusted IPs only.
  • TLS – Consider terminating HTTPS with a reverse proxy (Caddy or Nginx) and obtaining a cert via Let’s Encrypt.

User Permissions

  • Create a dedicated system user for running the ticketing container, e.g., ticketbot.
  • Ensure the user belongs to the docker group to execute Docker commands without sudo.

Pre‑Installation Checklist

  1. Verify Docker is running: docker version.
  2. Pull the ticketing image (see Installation section).
  3. Create a persistent volume directory: mkdir -p /opt/ticketdata.
  4. Back up any existing configuration files.

Installation & Setup

Below is a complete, reproducible installation workflow using Docker Compose. All commands are annotated with explanations to help you understand each step.

1. Pull The Official Ticketing Image

The example uses Wekan, a popular open‑source Kanban board that can be self‑hosted with minimal fuss.

1
docker pull $CONTAINER_IMAGE wekan/wekan:latest

Why $CONTAINER_IMAGE? Using a variable makes the command portable across scripts and avoids Jekyll‑specific placeholder conflicts.

2. Create a Docker Compose File

Save the following YAML as docker-compose.yml in a dedicated directory (/opt/ticketstack).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
version: "3.8"

services:
  wekan:
    image: $CONTAINER_IMAGE wekan/wekan:latest
    container_name: $CONTAINER_NAMES wekan
    restart: unless-stopped
    environment:
      - ROOT_URL=http://localhost:8080
      - PORT=8080
      - MONGO_URL=mongodb://mongo:27017/wekan
      - BCryptCost=12
      - SecretKey=CHANGE_THIS_TO_A_RANDOM_64CHAR_STRING
    ports:
      - "8080:8080"
    volumes:
      - $CONTAINER_VOLUME:/app/data
    depends_on:
      - mongo

  mongo:
    image: mongo:6.0
    container_name: $CONTAINER_NAMES mongo
    restart: unless-stopped
    volumes:
      - $CONTAINER_VOLUME/mongo:/data/db

Explanation of key fields:

  • $CONTAINER_IMAGE – Holds the Docker image name; replace with your registry if needed.
  • $CONTAINER_NAMES – Unique identifier for the container; helps in logs and monitoring.
  • $CONTAINER_VOLUME – Path to persistent storage; ensures data survives container restarts.
  • ROOT_URL – The public URL the app will be reachable at.
  • SecretKey – Must be a strong, random string; generate with openssl rand -hex 32.

3. Initialize Persistent Storage

1
mkdir -p $CONTAINER_VOLUME

If you prefer a named volume, you can define it in the compose file and let Docker manage it.

4. Launch The Stack

1
docker-compose up -d

Verify that both containers are healthy:

1
docker ps

You should see wekan and mongo listed with a STATUS of Up.

5. Secure The Installation

a. Generate a Strong Secret Key

1
2
SECRET=$(openssl rand -hex 32)
sed -i "s/CHANGE_THIS_TO_A_RANDOM_64CHAR_STRING/$SECRET/g" docker-compose.yml

Create a simple Caddyfile:

:80 {
    reverse_proxy localhost:8080
    encode gzip
}

Run Caddy with Docker:

1
2
3
4
5
6
7
docker run -d \
  --name caddy \
  -p 80:80 \
  -v $(pwd)/Caddyfile:/etc/caddy/Caddyfile \
  -v caddy_data:/data \
  -v caddy_config:/config \
  caddy:latest

Now access the ticketing UI at http://yourdomain.com.

6. Create An Admin Account

  1. Open the UI in a browser.
  2. Register a new account using an email address you control.
  3. During registration, set the Role to Admin.
  4. Save the credentials in a password manager; never store them in plain text.

7. Verify Integration With Git

If you host your infrastructure playbooks in Git, you can link tickets to commits:

1
2
git commit -m "Close #123: Update PostgreSQL to 15.4"
git push origin main

When the commit is pushed, a webhook (configured later) can automatically transition ticket #123 to Closed.


Configuration & Optimization

1. Core Configuration Options

SettingLocationDefaultRecommended ValueImpact
BCryptCostenvironment1212 (or 13 for stronger hashing)Determines password hash difficulty; higher values increase CPU usage.
SecretKeyenvironmentRandomUnique per instancePrevents session hijacking.
PORTenvironment808080 (behind proxy)Aligns with standard HTTP ports; keep internal port unchanged.
ROOT_URLenvironmenthttp://localhost:8080https://tickets.yourdomain.comEnables correct link generation in emails.

Edit the docker-compose.yml file and modify the relevant environment variables. Then run docker-compose up -d again to apply changes.

2. Security Hardening

  • Network Isolation – Place the container in a dedicated Docker network and block external access to the MongoDB port.
  • Read‑Only Filesystem – Run the container with --read-only and mount only the necessary volumes.
  • User Namespaces – Enable Docker’s user namespace remapping to avoid running as root inside the container.

Example Docker run command with hardening flags:

1
2
3
4
5
6
7
docker run -d \
  --name $CONTAINER_NAMES wekan \
  --restart unless-stopped \
  --read-only \
  --network $CONTAINER_NETWORK \
  -e ROOT_URL=$ROOT_URL \
  -
This post is licensed under CC BY 4.0 by the author.