Mission Log / Active / M-007 · eal-core01
M-007· eal-core01· Operational · v1

eal-core01 Infrastructure Node

Self-Hosted Private Cloud · Tailnet-Only HTTPS · Linux / Docker Operations

Role Designer / Operator
Platform Ubuntu + Docker
Access Tailnet-Only HTTPS
Window MAY 2026 — PRESENT
Phase v1 Operational
§ 01 · Overview

Mission summary.

A hardened private infrastructure node built from a donated mini PC.

eal-core01 is the first self-hosted infrastructure node for Endurance Aero Labs — a private cloud for engineering files, coursework, and project documentation, reachable from my Windows PC, iPhone, and iPad without ever touching the public internet.

It started as a free, retired HP EliteDesk 800 G3 Mini. The interesting part of the project was not "stand up a file server" — it was doing it under real constraints: a tight budget, a single internal drive bay, and a hard rule that the machine must never be exposed to the open internet or to untrusted Wi-Fi and LAN clients.

The v1 architecture answers those constraints directly: an internal SSD for live storage, a Dockerized Nextcloud stack for daily file access, Tailscale for a private encrypted network, Tailscale Serve for HTTPS, and a deny-by-default firewall with the application backend bound to localhost. The deliverable is a documented build — storage layout, access-control model, firewall policy, containerization, and a staged backup plan — not just a box that happens to serve files.

§ 02 · Requirements

Constraints & requirements.

Real-world constraints drove the architecture more than raw specs.

  • REQ-001 · Tailnet Access. The eal-core01 infrastructure node shall provide user-facing cloud services only to devices authenticated to the authorized Tailnet.
  • REQ-002 · Public Exposure Prevention. The eal-core01 infrastructure node shall not require public router port forwarding, Tailscale Funnel, or public DNS exposure for normal user access.
  • REQ-003 · Untrusted Network Isolation. The eal-core01 infrastructure node shall prevent unauthenticated devices on the local area network, open Wi-Fi networks, or the public internet from directly accessing the Nextcloud web service.
  • REQ-004 · Client File Access. The eal-core01 infrastructure node shall provide file access through standard Nextcloud clients on Windows, IOS, and Linux
  • REQ-005 · Localhost Backend Binding. The Nextcloud web backend shall bind to 127.0.0.1:8080 so that the raw application port is not directly exposed on the local area network or Tailnet.
  • REQ-006 · Live Data Partitioning. The eal-core01 infrastructure node shall store active Nextcloud user data on a dedicated /srv data partition separate from the operating-system root partition.
  • REQ-007 · Containerized Service Deployment. The eal-core01 infrastructure node shall deploy Nextcloud, MariaDB, Redis, and Nextcloud cron as Docker Compose services.
  • REQ-008 · DNS Filtering Service. The eal-core01 infrastructure node shall provide DNS-level filtering for Tailnet-connected client devices using AdGuard Home.
  • REQ-009 · Backup Role Separation. The external 4 TB drive shall be used as a backup target and shall not be treated as primary live storage until backup execution and restore verification are completed.
  • REQ-010 · Verification Evidence. The eal-core01 infrastructure node shall maintain verification evidence for service status, firewall posture, access-path behavior, storage layout, client connectivity, DNS filtering behavior, and backup/restore status.
§ 03 · Architecture

System architecture.

The v1 access path: authorized device to localhost-bound backend.

FIG · 01 — eal-core01 Private Cloud Access Model REV A · OPERATIONAL v1
FIG · 01 / EAL-CORE01 · PRIVATE CLOUD ACCESS MODEL CLIENTS PRIVATE OVERLAY eal-core01 HOST CLIENT · 01 Windows PC NEXTCLOUD DESKTOP · VFS CLIENT · 02 iPhone / iPad MOBILE CLIENTS UNTRUSTED Open Wi-Fi / LAN NO DIRECT ACCESS TAILNET Tailscale DEVICE AUTHORIZATION ENCRYPTED OVERLAY NO PORT FORWARDING NO FUNNEL HTTPS TS Serve TAILNET ONLY TS.NET CERT REVERSE PROXY UFW · DENY BY DEFAULT Firewall DENY INCOMING · ALLOW tailscale0 DOCKER · BACKEND Nextcloud Stack BOUND 127.0.0.1:8080 ONLY APP · MARIADB · REDIS · CRON STORAGE · LIVE /srv/nextcloud-data 2 TB SSD · DEDICATED PARTITION STORAGE · BACKUP WD Black 4 TB STAGED · NEXT CLOSURE GATE PROXY → LOCALHOST BACKUP (PLANNED) DENIED · NOT ROUTED · NOT BOUND AUTHORIZED PATH DENIED / NOT EXPOSED PLANNED
FIG · 01 · Authorized devices reach the node only through the Tailnet HTTPS URL. Tailscale Serve terminates TLS and reverse-proxies to a Docker backend bound to 127.0.0.1:8080 — so the raw Nextcloud service is never exposed on the LAN, the public internet, or even a direct Tailnet HTTP port.
§ 04 · Trade Results

Decision package.

Each decision scored against cost, failure modes, access risk, and backup needs.

The guiding tradeoff was a reliable, recoverable v1 over an expensive multi-drive NAS. Every row below is a decision I can defend, with the open item that still has to close before I'd call it done.

Decision Area Selected Baseline Why It Won Open Closure Item
Operating System Ubuntu Server 24.04 LTS Best fit for a general-purpose node running Docker, Tailscale, and Nextcloud on mini-PC hardware, with long-term support. Evaluate Ubuntu Pro + unattended security upgrades once backup is live.
Storage Layout Internal SSD live + external HDD backup Keeps live data on fast, reliable internal storage instead of a USB drive, while still using cheap high-capacity HDD for backup. Mount WD Black 4 TB as backup target; verify restore.
Remote Access Tailscale overlay only Encrypted private access with zero router port forwarding and no public DNS exposure. Keep the Tailnet device list controlled; never enable Funnel.
Web Frontend Tailscale Serve HTTPS Valid HTTPS inside the Tailnet while the Docker backend stays bound to localhost. Maintain trusted-domain / proxy config if the hostname changes.
NAS Platform TrueNAS / OMV deferred Considered, but the single-bay mini PC favored flexible Docker services over a ZFS storage appliance. Revisit if a multi-bay chassis is acquired.
Swipe to view full matrix

These are architecture-level decisions, not vendor lock-ins. The goal was to reduce risk before committing to a build.

§ 05 · Security Model

Access control.

What's intentionally open, what's intentionally closed, what's still hardening.

The security boundary is a private overlay network, not a public firewall ruleset. Nextcloud is reachable only by devices authorized in the Tailnet. The browser-facing service is HTTPS via Tailscale Serve; the Docker backend listens only on 127.0.0.1:8080. Defense comes from not being reachable in the first place, with the firewall as a second layer.

  • No public port forwarding. The router has no inbound rules for this service.
  • No Tailscale Funnel. Deliberately avoided — Funnel would publish the service to the open internet.
  • Deny-by-default firewall. UFW drops incoming traffic by default; only tailscale0 is allowed.
  • Localhost-only backend. Docker binds Nextcloud to 127.0.0.1:8080, blocking direct LAN or Tailnet HTTP access to the raw app.
  • Reverse-proxy correctness. Trusted proxies, forwarded headers, HTTPS overwrite, and official host/CLI URLs configured so the proxied app behaves correctly and securely.
  • Data-directory ownership. The Nextcloud data directory is owned by the container web user, preventing casual edits from the normal Linux account.
§ 06 · Storage

Live data & backup plan.

Why live storage and backup storage are deliberately separate roles.

The 2 TB SSD is the live device, partitioned deliberately: a root partition for the OS, Docker, applications, and logs, and a separate /srv partition for served data so user uploads can never fill the OS partition. Active files live under /srv/nextcloud-data.

The 4 TB external HDD is reserved strictly for backup and restore validation. I'm intentionally not using it as extra live capacity — live storage without backup just builds a bigger single point of failure. The closure gate for this project is a working, tested restore, not just a working server.

  • Live: internal SSD, /srv/nextcloud-data
  • App / config: /opt/eal/nextcloud
  • Backup target: WD Black 4 TB, dedicated backup volume
  • Backup scope: Nextcloud data, Compose files, env file, app volume, MariaDB dump, restore notes
§ 07 · Verification

Build & test log.

What was verified before treating the node as real storage.

MAY 2026

OS installed with deliberate partition layout

Fresh Ubuntu Server on the 2 TB SSD: EFI boot, root, and a dedicated /srv live-data partition — separation enforced at install time, not retrofitted.

CLOSED
MAY 2026

Container stack deployed & verified

Docker and Compose installed; MariaDB, Redis, the Nextcloud app, and the cron container brought up and confirmed healthy.

CLOSED
MAY 2026

Tailnet-only HTTPS established

Configured Tailscale Serve for a Tailnet-only HTTPS URL and moved the raw Docker backend to localhost-only binding — closing off LAN and direct-port access.

CLOSED
MAY 2026

Clients connected & upload path confirmed

Windows, iPhone, and iPad clients connected — Windows using virtual files to avoid pulling the full dataset onto limited local storage. Verified a test upload landed under the /srv-backed data directory.

CLOSED
MAY 2026

Access-control behavior verified

Confirmed the HTTPS URL works on-Tailnet and times out when a device leaves the Tailnet — proving the access boundary holds, not just that the happy path works.

CLOSED
NEXT

Backup & restore verification

Mount the 4 TB drive, write a backup procedure, run the first backup, and prove a restore. Until a restore is demonstrated, the node is "working," not "trustworthy."

OPEN
§ 08 · My Role

What I actually did.

End-to-end ownership, framed as transferable engineering skill.

I owned this node end-to-end: hardware selection under budget, OS install and partitioning, container deployment, Tailnet-only HTTPS, firewall hardening, client onboarding, and the backup architecture. More importantly, I treated a hobby-sounding task like an engineering project — requirements first, decisions documented, behavior verified.

  • Systems engineering. Turned a vague "private cloud" idea into requirements, constraints, tradeoffs, and a staged architecture with explicit closure gates.
  • Linux administration. Ubuntu Server, SSH, UFW, partitioning, permissions, and service directory layout.
  • Containerization. Nextcloud with MariaDB, Redis, and cron via Docker Compose.
  • Network security. Overlay-only access, no port forwarding, no Funnel, localhost-bound backend, reverse-proxy correctness.
  • Operational discipline. Live/backup separation and a verification-before-trust posture — including the open restore gate I refuse to skip.

The honest framing: this is operational v1, not a finished product. Its value is that it's a documented, defensible build — the same systems-engineering habits I apply to avionics work, demonstrated on infrastructure I run every day.

End of brief. This node is operational v1 — backup and restore verification is the next closure gate.