Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Port the site will be exposed on the host (requires firewall/DNS configured)
PORT=80
30 changes: 30 additions & 0 deletions .github/workflows/publish-docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Publish docs to GitHub Pages

on:
push:
branches: [ master ]
workflow_dispatch: {}

jobs:
publish:
name: Publish `docs/` ➜ GitHub Pages
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Configure Pages
uses: actions/configure-pages@v3

- name: Upload docs/
uses: actions/upload-pages-artifact@v1
with:
path: docs

- name: Deploy to GitHub Pages
uses: actions/deploy-pages@v1

- name: Post-deploy info
run: |
echo "Published docs/ to GitHub Pages. URL will be available in the Pages section of the repo settings."
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,32 @@ Nebulo is wholly an original piece of software: It doesn't use any other depende
# FAQ
For a growing collection of frequenty asked questions, [take a look here](FAQ.md).

## Website — public docs & self-hosting
You can make the repository documentation publicly reachable in two ways (both are configured in this repo):

1) **GitHub Pages (always-on, recommended)** — the repo is configured to publish the `docs/` folder automatically. The workflow runs on push to `master` and publishes to GitHub Pages.

Quick: Push your changes and the site will appear in the repository *Pages* settings (or at `https://<your-org-or-user>.github.io/Nebulo`).

2) **Self-host (Docker + nginx)** — use the provided `docker-compose.yml` to run a persistent site on any server.

- Start:
```bash
cp .env.sample .env # edit PORT if needed
./deploy/start.sh # starts container and waits for healthcheck
```
- Systemd (example): copy `deploy/nebulo-site.service` to `/etc/systemd/system/`, then `systemctl daemon-reload && systemctl enable --now nebulo-site`.

Notes and TLS:
- GitHub Pages gives HTTPS by default — no extra work required.
- For self-hosting: point your domain A record to the host, open the port in your firewall, and obtain a cert (Certbot or reverse-proxy). The nginx config includes `/.well-known/acme-challenge/` for ACME.
- The Docker Compose service is configured with `restart: unless-stopped` so it will automatically come back after reboots.

Security & availability checklist:
- Open only the required ports (80/443) and use HTTPS in production.
- Add a DNS A record for your domain and enable a firewall rule for the chosen port.
- Monitor uptime (systemd + `Restart=` policy + Docker healthcheck are included).

# Help wanted
Translations are important to reach as broad of an audience as possible and for non-english speakers to be able to use the app to its full extent. [Head over to the translation guide](TRANSLATING.md) to see how you can help!

Expand Down
22 changes: 22 additions & 0 deletions deploy/nebulo-site.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[Unit]
Description=Nebulo static site (docker-compose)
After=network.target docker.service
Requires=docker.service

[Service]
Type=oneshot
WorkingDirectory=/workspaces/Nebulo
EnvironmentFile=/workspaces/Nebulo/.env
ExecStart=/usr/bin/docker compose up -d nebulo-site
ExecStop=/usr/bin/docker compose down
RemainAfterExit=yes
TimeoutStartSec=120
Restart=on-failure

[Install]
WantedBy=multi-user.target

# Usage:
# 1) copy this file to /etc/systemd/system/nebulo-site.service
# 2) edit WorkingDirectory if you moved the repo
# 3) systemctl daemon-reload && systemctl enable --now nebulo-site.service
33 changes: 33 additions & 0 deletions deploy/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;

root /usr/share/nginx/html;
index index.html index.htm;

# Serve docsify (client-side) + static assets
location / {
try_files $uri $uri/ /index.html =404;
}

# Let's Encrypt ACME challenge
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /usr/share/nginx/html;
}

# Security headers (no HSTS here because TLS must be enabled before using it)
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header X-XSS-Protection "1; mode=block" always;

# Caching for assets
location ~* \.(?:css|js|svg|png|jpg|jpeg|gif|ico)$ {
expires 7d;
add_header Cache-Control "public, must-revalidate";
}

error_page 404 /404.html;
}
30 changes: 30 additions & 0 deletions deploy/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env bash
set -euo pipefail

# Start the Nebulo docs site (docker-compose)
# Usage: ./deploy/start.sh

ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"

# create .env from sample if missing
if [ ! -f .env ] && [ -f .env.sample ]; then
cp .env.sample .env
echo "Created .env from .env.sample — edit .env to change PORT"
fi

docker compose pull nebulo-site || true
docker compose up -d --remove-orphans

echo "Waiting for healthcheck (30s)..."
sleep 3
for i in {1..10}; do
if docker inspect --format='{{json .State.Health.Status}}' nebulo-site 2>/dev/null | grep -q healthy; then
echo "nebulo-site is healthy and serving docs/"
exit 0
fi
sleep 3
done

echo "If the container is not healthy, check logs: docker logs nebulo-site" >&2
exit 1
22 changes: 22 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: '3.8'

services:
nebulo-site:
image: nginx:stable-alpine
container_name: nebulo-site
ports:
- "${PORT:-80}:80"
volumes:
- ./docs:/usr/share/nginx/html:ro
- ./deploy/nginx.conf:/etc/nginx/conf.d/default.conf:ro
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL","wget -qS --spider http://127.0.0.1:${PORT:-80} || exit 1"]
interval: 30s
timeout: 5s
retries: 3
logging:
driver: "json-file"
options:
max-size: "5m"
max-file: "3"
5 changes: 5 additions & 0 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
* [Home](DNSRULE_WILDCARDS.md)
* [DNS wildcards](DNSRULE_WILDCARDS.md)
* [DNS-over-QUIC (DOQ)](DOQ.md)
* [Non-VPN mode](NONVPNMODE.md)
* [Full project on GitHub](https://github.com/Ch4t4r/Nebulo)
27 changes: 27 additions & 0 deletions docs/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Nebulo — Documentation</title>

<!-- docsify (client-side renderer for .md files) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/docsify@4/themes/vue.css"/>
<meta name="theme-color" content="#2d9bf0" />
</head>
<body>
<div id="app">Loading…</div>

<script>
window.$docsify = {
name: 'Nebulo',
repo: 'Ch4t4r/Nebulo',
loadSidebar: true,
subMaxLevel: 2,
homepage: 'DNSRULE_WILDCARDS.md'
}
</script>

<script src="https://cdn.jsdelivr.net/npm/docsify@4/lib/docsify.min.js"></script>
</body>
</html>