Post

Put Self Hosting On Your Cv

Put Self Hosting On Your Cv

Put Self Hosting On Your Cv

Introduction

In today’s competitive DevOps landscape, simply listing “Docker” or “Kubernetes” on a résumé is no longer enough. Recruiters and hiring managers are increasingly looking for concrete evidence that a candidate can design, deploy, and maintain end‑to‑end self‑hosted environments. The ability to spin up a reliable homelab, automate deployments, manage secrets, and harden security demonstrates a depth of operational knowledge that cannot be faked through certifications alone.

The Reddit discussion that sparked this guide highlighted a simple truth: a well‑documented self‑hosted setup on a curriculum vitae signals that the author has wrestled with the “boring” yet critical aspects of system engineering — monitoring, logging, version control, CI/CD pipelines, and security hardening — while also delivering measurable uptime. For senior‑level roles, this hands‑on experience often outweighs theoretical knowledge.

This comprehensive guide walks you through the entire lifecycle of building a production‑grade self‑hosted stack that you can proudly showcase on your CV. We will cover:

  • The core concepts behind self‑hosted infrastructure and why they matter to employers.
  • Prerequisites, installation steps, and configuration best practices for a typical stack (Docker, Docker‑Compose, Prometheus, Grafana, and a lightweight Git‑server).
  • Security hardening, performance tuning, and scaling considerations.
  • Real‑world troubleshooting techniques and maintenance routines.

By the end of this article, you will have a reproducible, documented environment that you can reference in your résumé, LinkedIn profile, or personal portfolio. You will also understand how to articulate the value of each component to non‑technical hiring managers, turning a hobby project into a compelling career asset.

Keywords: self‑hosted, homelab, DevOps, infrastructure automation, open‑source, container orchestration, monitoring, security, CI/CD, GitOps.


Understanding the Topic

What Is a Self‑Hosted Stack?

A self‑hosted stack refers to a collection of services — such as web applications, databases, monitoring tools, and version‑control repositories — that you install, configure, and operate on hardware or virtual machines you control. Unlike SaaS alternatives, self‑hosted solutions give you full ownership of the runtime environment, allowing you to customize networking, storage, and security policies to meet exacting operational requirements.

Historical Context

The concept of self‑hosting dates back to the early 2000s when sysadmins began running their own mail, web, and file servers on dedicated boxes. With the advent of containerization, the paradigm shifted: developers could now package entire applications into lightweight, portable images that run consistently across environments. Docker, introduced in 2013, popularized this approach, and Docker‑Compose soon after enabled multi‑container orchestration on a single host.

Core Features and Capabilities

  • Isolation – Containers provide process‑level isolation, ensuring that one service’s failure does not cascade to others.
  • Reproducibility – Infrastructure as Code (IaC) manifests (Dockerfiles, docker‑compose.yml) allow you to recreate the exact same environment on any machine.
  • Version Control – All configuration files can be stored in Git, enabling rollbacks and collaborative development.
  • Automation – Scripts and CI pipelines can automatically build, test, and deploy updates without manual intervention.
  • Observability – Integration with Prometheus, Grafana, and Loki provides real‑time metrics, dashboards, and logs.

Pros and Cons

AdvantagesChallenges
Full control over upgrades, patches, and configurationRequires disciplined operational hygiene
Ability to tailor performance and security settingsResource constraints on low‑end hardware
Demonstrates end‑to‑end DevOps skillsLearning curve for advanced networking and storage
Open‑source ecosystem offers abundant toolingMaintenance overhead if not automated

Use Cases and Scenarios

  • Personal Homelab – Experimentation with new technologies, learning, and hobby projects.
  • Development Environments – Providing developers with identical local stacks that mirror production.
  • Edge Computing – Deploying lightweight services on edge devices with constrained resources.
  • Small‑Scale Production – Hosting internal tools (e.g., issue trackers, CI runners) for teams of 5‑20 engineers.

The self‑hosted movement continues to mature, with projects like Kubernetes offering production‑grade orchestration for those ready to scale beyond a single host. However, for many DevOps professionals, a well‑designed Docker‑Compose stack remains the sweet spot: it offers sufficient depth to showcase operational expertise without the overhead of managing a full‑blown cluster. Emerging trends include GitOps pipelines, infrastructure‑as‑code with Terraform, and zero‑trust networking models that further harden self‑hosted deployments.

Comparison to Alternatives

SolutionTypical Use‑CaseComplexityCV Impact
SaaS (e.g., GitHub, GitLab.com)Simple code hostingLowMinimal – indicates usage only
Managed Kubernetes (EKS, GKE)Large‑scale productionHighModerate – shows cloud expertise
Self‑Hosted Docker‑Compose + Prometheus/GrafanaHomelab, internal toolsMediumHigh – demonstrates full lifecycle ownership

Prerequisites

Before embarking on the installation, ensure your environment meets the following baseline requirements.

RequirementMinimum SpecificationRecommended
Hardware4 CPU cores, 8 GB RAM, 100 GB SSD8 CPU cores, 16 GB RAM, 250 GB SSD
Operating SystemUbuntu 22.04 LTS or Debian 12CentOS 9 Stream or Rocky 9
Docker EngineDocker 24.0.xDocker 24.0.x with BuildKit enabled
Docker‑ComposeDocker‑Compose 2.20.xDocker‑Compose 2.23.x
NetworkStatic IP or Dynamic DNS for external accessGigabit Ethernet, port‑forwarding enabled
User Permissionssudo access for initial setupDedicated docker group membership
SecurityOpenSSH 9.0+UFW or firewalld with default deny inbound

Pre‑Installation Checklist

  1. Update the OS packages: sudo apt update && sudo apt upgrade -y.
  2. Install prerequisite packages: sudo apt install -y curl git ufw.
  3. Configure a non‑root user with sudo privileges and add to the docker group: sudo usermod -aG docker $USER.
  4. Verify Docker daemon status: systemctl status docker.
  5. Open required ports (e.g., 80, 443, 3000) in the firewall: sudo ufw allow 80/tcp && sudo ufw allow 443/tcp && sudo ufw allow 3000/tcp && sudo ufw enable.

External resources:


Installation & Setup

The following sections walk you through a reproducible installation of a minimal self‑hosted stack that includes a Git‑server (Gitea), a Prometheus monitoring stack, and a Grafana dashboard. All components are defined in declarative configuration files, ensuring repeatability.

1. Directory Structure

Create a dedicated directory for the stack and organize files as follows:

1
2
3
4
5
6
7
8
9
10
11
selfhost/
├── docker-compose.yml
├── gitea/
│   ├── app/
│   └── conf/
├── prometheus/
│   └── prometheus.yml
└── grafana/
    └── provisioning/
        └── dashboards/
            └── dashboard.yaml

This layout separates each service’s data, configuration, and provisioning artifacts, making it easy to version‑control and back up.

2. Docker‑Compose Manifest

Below is a complete docker-compose.yml that defines the three services. Notice the use of environment variables and volume mappings that persist data across container restarts.

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
version: "3.9"

services:
  gitea:
    image: gitea/gitea:1.23
    container_name: $CONTAINER_NAMES_gitea
    restart: unless-stopped
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__INSTALL_LOCK=1
    volumes:
      - ./gitea/app:/data/app
      - ./gitea/conflogs:/data/log
      - ./gitea/conf:/etc/gitea
    ports:
      - "3000:3000"
      - "22:22"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

  prometheus:
    image: prom/prometheus:v2.51
    container_name: $CONTAINER_NAMES_prometheus
    restart: unless-stopped
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    ports:
      - "9090:9090"
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
      - "--storage.tsdb.path=/prometheus"
      - "--web.enable-admin-api"

  grafana:
    image: grafana/grafana:10.4
    container_name: $CONTAINER_NAMES_grafana
    restart: unless-stopped
    ports:
      - "3001:3000"
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=$GRAFANA_ADMIN_PASSWORD

volumes:
  prometheus_data:
  grafana_data:

Explanation of Key Sections

  • container_name – Uses the $CONTAINER_NAMES_* placeholder to maintain consistency with Jekyll‑compatible templating.
  • restart: unless-stopped – Guarantees automatic recovery after host reboots.
  • Healthcheck – Periodically validates that Gitea is reachable, providing early detection of failures.
  • Volumes – Persist application data (app, log, conf) and metrics (prometheus_data, grafana_data).
  • Ports – Map host ports to container ports for external access.

To launch the stack, execute:

1
2
cd selfhost
docker compose up -d

Verify container status:

1
docker ps --filter "name=$CONTAINER_NAMES_"

3. Configuration Files

Gitea Configuration (gitea/conf/app.ini)

This post is licensed under CC BY 4.0 by the author.