Skip to main content

Internal Documentation System Setup

Architecture Decision

We use a Docs-as-Code approach.

  • Engine: Docusaurus (Static Site Generator).
  • Hosting: Coolify (Hetzner VPS).
  • Security: Nginx Basic Auth (User: admin).
  • Strategy: Documentation lives in the oxaway-internal-docs repo and is deployed automatically via Docker.

1. Local Initialization

If you need to re-initialize the documentation project from scratch, follow these steps.

Prerequisites

  • Node.js 18+
  • Docker (for local testing)

Step-by-Step

  1. Scaffold the Project

    npx create-docusaurus@latest oxaway-internal-docs classic
    cd oxaway-internal-docs
  2. Clean Boilerplate Remove the default tutorial and blog to keep the repo clean.

    rm -rf docs/* blog src/pages/index.js
  3. Install Dependencies

    npm install
  4. Local Development Start the local server to preview changes.

    npm run start
    # Opens at http://localhost:3000

2. Docker Configuration (The Build Artifact)

We use a custom Dockerfile to serve the static assets via Nginx and enforce Basic Authentication (since these are private internal docs).

Create a file named Dockerfile in the project root:

# Stage 1: Build the Static Site
FROM node:lts-alpine as build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Stage 2: Serve with Nginx + Security
FROM nginx:alpine

# Install utils to create password file
RUN apk add --no-cache apache2-utils

# --- SECURITY CONFIGURATION ---
# Create the password file.
# REPLACE 'ChangeMe123!' with a strong password before committing!
RUN htpasswd -bc /etc/nginx/.htpasswd admin ChangeMe123!

# Configure Nginx to require the password
RUN echo 'server { \
listen 80; \
server_name localhost; \
location / { \
root /usr/share/nginx/html; \
index index.html index.htm; \
try_files $uri $uri/ /index.html; \
auth_basic "OxaWay Internal Docs"; \
auth_basic_user_file /etc/nginx/.htpasswd; \
} \
}' > /etc/nginx/conf.d/default.conf

# Copy the built assets from Stage 1
COPY --from=build /app/build /usr/share/nginx/html

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

3. Deployment to Coolify

We deploy this as a Private Repository service on our Hetzner instance.

Configuration Steps

  1. Log in to Coolify (panel.oxaway.ai).
  2. New Resource -> Private Repository (GitHub).
  3. Select Repo: oxaway-internal-docs.
  4. Configuration Fields:
    • Service Name: oxaway-internal-docs
    • Build Pack: Dockerfile (Do NOT use Nixpacks).
    • Docker Image Location: /Dockerfile
    • Port: 80
  5. Environment Variables: None required (Password is baked into Dockerfile for simplicity, or can be moved to ENV vars in Phase 2).

DNS Setup

  1. Go to AWS Route 53.
  2. Create an A Record:
    • Name: docs.oxaway.ai
    • Value: <HETZNER_IP_ADDRESS>
  3. In Coolify Service settings, set Domains to https://docs.oxaway.ai.

4. Maintenance Workflow

Updating Documentation

  1. Edit Markdown files in docs/.
  2. Commit and Push to main.
    git add .
    git commit -m "docs: update infrastructure runbook"
    git push origin main
  3. Coolify webhook triggers a rebuild.
  4. Changes live in ~60 seconds.

Troubleshooting

  • "403 Forbidden": You likely entered the wrong Basic Auth credentials.
  • "Deploy Failed": Check Coolify Build Logs. Usually a syntax error in the Markdown preventing Docusaurus from compiling.