Post

Personal Server Usage Documentation

Personal Server Usage Documentation

Overview

This document describes my personal server infrastructure, how it’s used in development and collaboration, and the rationale behind key security and networking decisions. It is not a guide or tutorial — it’s a blueprint of my system, my workflow, and my control.

We’ll break it down into three areas:

  • Security
  • Networking
  • Usage

1. Security

Access Control

  • Development access uses SSH keys for full terminal control when working from trusted devices, like my laptop or desktop.
  • Server access, however, is much more restricted. The server does not store full SSH keys for GitHub or other services, reducing risk in case of unauthorized access through CI systems or shared tooling.

Personal Access Tokens (PATs)

Because the server still needs to interact with GitHub for tasks like CI/CD or automation, I rely on GitHub Personal Access Tokens (PATs). These are carefully scoped and managed to balance functionality with security. Here’s how I approach them:

  • Read-only CI/CD PAT

    • Purpose: To securely clone my private server repository, which contains essential bash automation and installation scripts.
    • Storage: Hardcoded locally on the server (never exposed externally).
    • Scope: Fine-grained access to only one repo.
    • Auth Method:

      1
      2
      
      git config --global credential.helper store
      git clone https://<username>:<PAT>@github.com/<Org>/<Repo>.git
      

      This stores the token in plain text under ~/.git-credentials, which is acceptable for me given its read-only nature and limited scope.

  • Kubernetes ARC PAT

    • Purpose: To authenticate Actions Runner Controller (ARC) for self-hosted runners using GitHub.
    • Scope: Requires admin:org permission (needed to register the runner with the organization, but does not grant direct read or write access to repositories).
    • Recommended: Eventually transition to GitHub App authentication for tighter scoping and repo-specific access (see GitHub ARC Auth Docs).

Note: Server secrets are never shared outside of GitHub.com and the machine itself. There is no open inbound SSH access outside my own Tailscale VPN IPs.

Reminder: Never push these secrets to GitHub or expose them on any public or cloud service—keep them local, keep them secure.


2. Networking

I maintain a small ecosystem of personal devices:

  • Android mobile phone (ADB access)
  • MacBook (SSH access)
  • Linux dev machine (main)
  • Personal server (CI/CD, syncing, storage)

These are interconnected using Tailscale, which provides:

  • Encrypted P2P mesh VPN via WireGuard
  • DNS resolution across devices
  • Cross-platform remote access (e.g., ADB over VPN)

Access Matrix

DeviceAccessesNotes
MacBookDev PC, Server via SSHUsed for remote work
Dev MachineServer via SSHPrimary development workflow
Mobile PhoneADB + Server Data AccessLightweight device for accessing notes/bookmarks remotely

3. Usage

The server isn’t just for builds. It’s part of a broader goal: own my data and stay productive remotely. Here’s how services are segmented:

SSH (Private Access Only)

  • Used only by me.
  • Only reachable via Tailscale IPs.
  • Default port not used (port randomization for obfuscation).
  • 2FA (or hardware key) required for authentication
  • Port: 32918/tcp

Tailscale Setup

  • Purpose: Tailscale provides a secure private network that lets me access my server’s services without exposing them publicly on the internet.
  • How it works: Tailscale uses WireGuard to create an encrypted mesh network between my devices and the server, making secure connections simple without complex firewall or NAT setup.
  • HTTPS Certificates: Tailscale Serve automatically obtains trusted HTTPS certificates from Let’s Encrypt for services accessible via your tailnet (e.g., https://servicename.tailxxxxx.ts.net).
  • Free Domains: With Tailscale MagicDNS, I get free, reliable subdomains under ts.net, saving costs on domain registration and simplifying internal service addressing long-term.
  • Advantages:

    • No manual certificate management or firewall port forwarding needed.
    • TLS certificates are tied to your Tailscale identity and valid only on your private network.
    • Automatic device key rotation and authentication ensure secure access.
  • Renewal: Certificates are valid for 90 days; renewal is automatic as long as Tailscale Serve is active and reachable.

Note: I chose Tailscale because it unifies secure networking, private DNS (MagicDNS), free domain management, and easy HTTPS for internal apps, greatly simplifying server management and reducing long-term costs.

GitHub CI/CD (ARC Runners)

  • Self-hosted GitHub Actions runners deployed using Kubernetes ARC
  • Used for automating builds, tests, and deployments
  • Runs fully isolated within a Helm-managed Kubernetes cluster — each job runs in its own Docker container
  • Authenticated using a scoped PAT (see PATs section for details)

With the automation infrastructure in place, I now focus on managing and safeguarding my essential data, including private services like my centralized bookmark backend and the automated backup processes that keep everything secure and recoverable.

Bookmarks (Linkwarden)

  • Purpose: A private, centralized bookmark backend for storing and organizing web links.
  • Port: 3000/tcp (internal Docker port; accessible via Tailscale at https://linkwarden.tailxxx.ts.net).
  • Backend: Linkwarden, self-hosted.
  • Security:

    • Exposed only over Tailscale VPN.
    • Fronted with tsdproxy for consistent HTTPS access.
    • Access restricted to Tailscale IP allowlist.

Project Management (Plane)

  • Purpose: A collaborative project management and task-tracking tool for planning and coordination with trusted teammates.
  • Port: 3000/tcp (internal Docker port; accessible via Tailscale at https://plane.tailxxx.ts.net).
  • Software: Plane, self-hosted.
  • Security:

    • VPN-only access via Tailscale.
    • Proxied through tsdproxy with IP filtering.
    • Enforced least-privilege principles on data endpoints.

This service supports real-time collaboration, helping us keep project planning both centralized and secure.


Backups

Since both Linkwarden and Plane store data locally on my server and not in GitHub, robust backup strategies are critical. For this, I use Cloudflare R2 (Cloudflare R2 documentation), which offers 10GB of free storage, more than enough for my needs.

  • Linkwarden: I back up the pgdata directory, which contains all essential Postgres data.
  • Plane: I use the built-in bash backup script provided by Plane to generate a local archive of the data.

Both services’ backups are stored locally first, then pushed to Cloudflare R2 via a cron job running every 12 hours. This ensures that my critical data is not only protected on my personal server but also securely backed up offsite, guarding against hardware failures or other disasters.


Password Management & Fire Scenario

While I self-host many of my services, I don’t self-host my password manager anymore. Instead, I store my passwords in Google Drive. This ensures that they’re accessible even if my home network is down, like during a power outage at home but not at school. This way, I can always reach my passwords from my android phone if I need them during an exam.

For managing my passwords, I use KeePassXC. It lets me keep all my credentials in a single, encrypted vault file, balancing security and portability.

Note: Don’t make the same mistake I did, use KeePassXC (not the old KeePass) for easier cross-platform support. When I switched from Windows to Linux, KeePass required me to mess with Wine and plugins. With KeePassXC, OTP (one-time password) support is built-in, no plugin headaches!

To prepare for worst-case scenarios, such as a house fire where all my devices are destroyed, I maintain an encrypted backup of this vault in a private GitHub repository. I carry a USB key with my SSH keys at all times. This allows me to authenticate into GitHub from any device, recover my password vault, and set up KeePassXC anywhere, ensuring I can regain access to all my accounts in case I lost access to all my devices.

Note: This approach works well for me, but it might not be the best for everyone. Feel free to comment with suggestions, pros, cons, or improvements, I’m always open to refining my setup!


Expansion Possibilities

Some areas I plan to extend:

  • Logs + Monitoring:

    • Use Loki for log aggregation.
    • Prometheus for metrics collection.
    • Grafana for building a centralized monitoring dashboard.

Final Notes

If I ever scale up to a small startup, this system is built with that in mind, from authentication, to endpoints, to zero-trust networking.

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