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-docsrepo 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
-
Scaffold the Project
npx create-docusaurus@latest oxaway-internal-docs classic
cd oxaway-internal-docs -
Clean Boilerplate Remove the default tutorial and blog to keep the repo clean.
rm -rf docs/* blog src/pages/index.js -
Install Dependencies
npm install -
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
- Log in to Coolify (
panel.oxaway.ai). - New Resource -> Private Repository (GitHub).
- Select Repo:
oxaway-internal-docs. - Configuration Fields:
- Service Name:
oxaway-internal-docs - Build Pack:
Dockerfile(Do NOT use Nixpacks). - Docker Image Location:
/Dockerfile - Port:
80
- Service Name:
- Environment Variables: None required (Password is baked into Dockerfile for simplicity, or can be moved to ENV vars in Phase 2).
DNS Setup
- Go to AWS Route 53.
- Create an A Record:
- Name:
docs.oxaway.ai - Value:
<HETZNER_IP_ADDRESS>
- Name:
- In Coolify Service settings, set Domains to
https://docs.oxaway.ai.
4. Maintenance Workflow
Updating Documentation
- Edit Markdown files in
docs/. - Commit and Push to
main.git add .
git commit -m "docs: update infrastructure runbook"
git push origin main - Coolify webhook triggers a rebuild.
- 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.