somratpro commited on
Commit
42a7d7b
Β·
1 Parent(s): 1c85513

feat: add open-source files, fix critical bugs, rewrite README with Duplicate Space button

Browse files

- fix: huggingface_hub version was non-existent (==0.34.4), unpinned to latest
- fix: N8N_SECURE_COOKIE defaulted to true, breaking login behind HF TLS proxy (now false)
- fix: WebSocket upgrade handler now forwards Upgrade/Connection headers correctly
- fix: removed deprecated local_dir_use_symlinks param from n8n-sync.py
- fix: chmod 700 on /home/node/.n8n to satisfy n8n permission check
- feat: N8N_VERSION build ARG for optional n8n version pinning via HF Space Variable
- feat: N8N_BASIC_AUTH_ACTIVE=true by default with warning if password not set
- feat: full README rewrite with Duplicate Space button, secrets table, architecture docs
- chore: add CONTRIBUTING.md, CODE_OF_CONDUCT.md, SECURITY.md, CHANGELOG.md
- chore: add .env.example with all variables documented
- chore: add .gitignore

Files changed (11) hide show
  1. .env.example +95 -0
  2. .gitignore +33 -0
  3. CHANGELOG.md +29 -0
  4. CODE_OF_CONDUCT.md +27 -0
  5. CONTRIBUTING.md +48 -0
  6. Dockerfile +5 -2
  7. README.md +194 -32
  8. SECURITY.md +29 -0
  9. health-server.js +19 -7
  10. n8n-sync.py +0 -1
  11. start.sh +14 -1
.env.example ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # =============================================================================
2
+ # Hugging8n β€” Environment Variables Reference
3
+ # Copy to .env and fill in your values before running locally.
4
+ # On HuggingFace Spaces, add Secrets and Variables in Settings β†’ Variables and secrets.
5
+ # =============================================================================
6
+
7
+ # -----------------------------------------------------------------------------
8
+ # REQUIRED β€” Basic Auth (set these as Secrets on HF Spaces)
9
+ # -----------------------------------------------------------------------------
10
+
11
+ # Username for n8n basic auth login
12
+ N8N_BASIC_AUTH_USER=admin
13
+
14
+ # Password for n8n basic auth login. REQUIRED to protect your instance.
15
+ # Generate a strong password: openssl rand -base64 24
16
+ N8N_BASIC_AUTH_PASSWORD=
17
+
18
+ # -----------------------------------------------------------------------------
19
+ # RECOMMENDED β€” Persistent Backup (set these as Secrets on HF Spaces)
20
+ # -----------------------------------------------------------------------------
21
+
22
+ # Your Hugging Face write token (to create/update the backup dataset)
23
+ # Get one at: https://huggingface.co/settings/tokens
24
+ HF_TOKEN=
25
+
26
+ # Your Hugging Face username (owner of the backup dataset)
27
+ # If not set, inferred from SPACE_AUTHOR_NAME automatically on HF Spaces
28
+ HF_USERNAME=
29
+
30
+ # Name of the private dataset repo used for backup (auto-created on first run)
31
+ BACKUP_DATASET_NAME=hugging8n-backup
32
+
33
+ # How often to sync the backup, in seconds
34
+ SYNC_INTERVAL=180
35
+
36
+ # -----------------------------------------------------------------------------
37
+ # OPTIONAL β€” n8n Configuration
38
+ # -----------------------------------------------------------------------------
39
+
40
+ # Timezone for n8n schedule triggers (e.g. Asia/Dhaka, Europe/London, US/Eastern)
41
+ GENERIC_TIMEZONE=UTC
42
+
43
+ # n8n encryption key β€” protects stored credentials. Persisted in backup.
44
+ # Generate with: openssl rand -hex 32
45
+ # WARNING: if you lose this key and your backup, all credentials are lost.
46
+ N8N_ENCRYPTION_KEY=
47
+
48
+ # Override the auto-detected Space hostname (leave blank on HF Spaces)
49
+ SPACE_HOST_OVERRIDE=
50
+
51
+ # -----------------------------------------------------------------------------
52
+ # OPTIONAL β€” Keep-Alive
53
+ # -----------------------------------------------------------------------------
54
+
55
+ # UptimeRobot Main API key for creating an external keep-alive monitor
56
+ # Get one at: https://uptimerobot.com β†’ My Settings β†’ API Settings β†’ Main API Key
57
+ # This is NOT needed as a HF Space Secret β€” it's only used by setup-uptimerobot.sh
58
+ UPTIMEROBOT_API_KEY=
59
+
60
+ # Custom monitor name (defaults to "Hugging8n <space-host>")
61
+ UPTIMEROBOT_MONITOR_NAME=
62
+
63
+ # UptimeRobot ping interval in minutes (default: 5)
64
+ UPTIMEROBOT_INTERVAL=5
65
+
66
+ # Comma-separated UptimeRobot alert contact IDs (optional)
67
+ UPTIMEROBOT_ALERT_CONTACTS=
68
+
69
+ # -----------------------------------------------------------------------------
70
+ # ADVANCED β€” n8n Internals (usually leave as defaults)
71
+ # -----------------------------------------------------------------------------
72
+
73
+ # Disable n8n basic auth (not recommended β€” leaves your instance unprotected)
74
+ # N8N_BASIC_AUTH_ACTIVE=false
75
+
76
+ # Internal n8n port (default: 5678)
77
+ N8N_PORT=5678
78
+
79
+ # Public proxy port exposed by HF Spaces (default: 7861)
80
+ PUBLIC_PORT=7861
81
+
82
+ # Disable n8n telemetry (default: false)
83
+ N8N_DIAGNOSTICS_ENABLED=false
84
+
85
+ # Disable n8n personalization prompts (default: false)
86
+ N8N_PERSONALIZATION_ENABLED=false
87
+
88
+ # -----------------------------------------------------------------------------
89
+ # BUILD-TIME VARIABLE (HF Spaces: add as Variable, not Secret)
90
+ # -----------------------------------------------------------------------------
91
+
92
+ # Pin a specific n8n version for reproducibility (default: latest)
93
+ # Example: 1.90.0
94
+ # On HF Spaces, add this as a Variable (not Secret) so it's passed as a build arg.
95
+ N8N_VERSION=latest
.gitignore ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Environment
2
+ .env
3
+ .env.local
4
+ .env.*.local
5
+
6
+ # n8n local data
7
+ .n8n/
8
+
9
+ # Python
10
+ __pycache__/
11
+ *.py[cod]
12
+ *.pyo
13
+ *.pyd
14
+ .Python
15
+ *.egg-info/
16
+ dist/
17
+ build/
18
+ .venv/
19
+ venv/
20
+
21
+ # Node
22
+ node_modules/
23
+ npm-debug.log*
24
+
25
+ # OS
26
+ .DS_Store
27
+ Thumbs.db
28
+
29
+ # Editor
30
+ .vscode/
31
+ .idea/
32
+ *.swp
33
+ *.swo
CHANGELOG.md ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [1.0.0] - 2026-04-22
6
+
7
+ ### πŸŽ‰ Initial Release
8
+
9
+ #### Features
10
+
11
+ - **Self-hosted n8n** β€” runs the latest n8n on HuggingFace Spaces Docker with zero external database requirements (uses SQLite)
12
+ - **Persistent backup** β€” automatically backs up `/home/node/.n8n` (workflows, credentials, SQLite DB, encryption key) to a private HF Dataset via `huggingface_hub`
13
+ - **Safe SQLite backup** β€” uses `sqlite3 .backup` for a consistent hot-copy of the live database
14
+ - **Auto-restore on startup** β€” restores the full n8n state from the dataset before starting n8n
15
+ - **Graceful shutdown** β€” runs a final backup pass on `SIGTERM` / `SIGINT` before exiting
16
+ - **Health endpoint** β€” `/health` on port 7861 returns sync status and service info
17
+ - **Proxy server** β€” lightweight Node.js reverse proxy forwards HTTP and WebSocket traffic from port 7861 to n8n on port 5678
18
+ - **UptimeRobot integration** β€” `setup-uptimerobot.sh` creates an external keep-alive monitor for the `/health` endpoint
19
+ - **Basic auth** β€” n8n basic auth enabled by default; set `N8N_BASIC_AUTH_USER` and `N8N_BASIC_AUTH_PASSWORD` to secure your instance
20
+ - **Timezone support** β€” set `GENERIC_TIMEZONE` for schedule trigger accuracy
21
+ - **Optional n8n version pinning** β€” pass `N8N_VERSION` as a HF Space Variable to pin a specific n8n release
22
+
23
+ #### Architecture
24
+
25
+ - `Dockerfile` β€” builds on `node:22-slim`, installs n8n and Python sync dependencies
26
+ - `start.sh` β€” validates config, restores backup, starts sync loop, proxy, and n8n
27
+ - `n8n-sync.py` β€” manages backup/restore using `huggingface_hub`
28
+ - `health-server.js` β€” lightweight HTTP + WebSocket reverse proxy with `/health` and `/status` endpoints
29
+ - `setup-uptimerobot.sh` β€” optional one-shot script to create an UptimeRobot monitor
CODE_OF_CONDUCT.md ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Code of Conduct
2
+
3
+ ## Our Pledge
4
+
5
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
6
+
7
+ ## Our Standards
8
+
9
+ **Positive behavior includes:**
10
+ - Using welcoming and inclusive language
11
+ - Being respectful of differing viewpoints
12
+ - Gracefully accepting constructive criticism
13
+ - Focusing on what is best for the community
14
+
15
+ **Unacceptable behavior includes:**
16
+ - Trolling, insulting, or derogatory comments
17
+ - Public or private harassment
18
+ - Publishing others' private information without permission
19
+ - Other conduct which could reasonably be considered inappropriate
20
+
21
+ ## Enforcement
22
+
23
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting the maintainer. All complaints will be reviewed and investigated.
24
+
25
+ ## Attribution
26
+
27
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.0.
CONTRIBUTING.md ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Contributing to Hugging8n
2
+
3
+ Thanks for your interest in contributing! ♾️
4
+
5
+ ## How to Contribute
6
+
7
+ ### Bug Reports
8
+ - Open an issue with a clear description
9
+ - Include your HF Space logs if possible
10
+ - Mention the n8n version you're using (check Space logs on startup)
11
+
12
+ ### Feature Requests
13
+ - Open an issue with the `enhancement` label
14
+ - Describe the use case β€” why is this needed?
15
+
16
+ ### Pull Requests
17
+ 1. Fork the repo
18
+ 2. Create a feature branch: `git checkout -b feature/my-feature`
19
+ 3. Make your changes
20
+ 4. Test locally with Docker: `docker build -t hugging8n . && docker run -p 7861:7861 --env-file .env hugging8n`
21
+ 5. Commit with a clear message
22
+ 6. Push and open a PR
23
+
24
+ ### Code Style
25
+ - Shell scripts: use `set -e`, quote variables, comment non-obvious logic
26
+ - Keep it simple β€” this project should stay easy to understand
27
+ - No unnecessary dependencies
28
+
29
+ ### Testing
30
+ - Test with and without `HF_TOKEN` (backup enabled and disabled)
31
+ - Test with and without `N8N_BASIC_AUTH_ACTIVE`
32
+ - Verify the `/health` endpoint responds correctly
33
+ - Verify n8n loads in the browser via the proxy
34
+
35
+ ## Development Setup
36
+
37
+ ```bash
38
+ cp .env.example .env
39
+ # Fill in your values
40
+ docker build -t hugging8n .
41
+ docker run -p 7861:7861 --env-file .env hugging8n
42
+ ```
43
+
44
+ Then open `http://localhost:7861` β€” you should see the n8n UI.
45
+
46
+ ## Questions?
47
+
48
+ Open an issue or start a discussion. We're friendly! 🀝
Dockerfile CHANGED
@@ -1,5 +1,7 @@
1
  FROM node:22-slim
2
 
 
 
3
  ENV DEBIAN_FRONTEND=noninteractive \
4
  N8N_PORT=5678 \
5
  HF_HUB_DISABLE_PROGRESS_BARS=1 \
@@ -14,11 +16,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
14
  python3-pip \
15
  sqlite3 \
16
  tini \
17
- && pip3 install --no-cache-dir --break-system-packages huggingface_hub==0.34.4 \
18
- && npm install -g n8n@latest \
19
  && rm -rf /var/lib/apt/lists/*
20
 
21
  RUN mkdir -p /home/node/app /home/node/.n8n && \
 
22
  chown -R node:node /home/node
23
 
24
  WORKDIR /home/node/app
 
1
  FROM node:22-slim
2
 
3
+ ARG N8N_VERSION=latest
4
+
5
  ENV DEBIAN_FRONTEND=noninteractive \
6
  N8N_PORT=5678 \
7
  HF_HUB_DISABLE_PROGRESS_BARS=1 \
 
16
  python3-pip \
17
  sqlite3 \
18
  tini \
19
+ && pip3 install --no-cache-dir --break-system-packages huggingface_hub \
20
+ && npm install -g n8n@${N8N_VERSION} \
21
  && rm -rf /var/lib/apt/lists/*
22
 
23
  RUN mkdir -p /home/node/app /home/node/.n8n && \
24
+ chmod 700 /home/node/.n8n && \
25
  chown -R node:node /home/node
26
 
27
  WORKDIR /home/node/app
README.md CHANGED
@@ -5,53 +5,215 @@ colorFrom: blue
5
  colorTo: indigo
6
  sdk: docker
7
  app_port: 7861
8
- pinned: false
9
  license: mit
10
  ---
11
 
12
- # Hugging8n
 
 
 
 
13
 
14
- Run a self-hosted n8n instance on Hugging Face Spaces without external database services.
15
 
16
- This Space uses:
17
 
18
- - `n8n` running locally on port `5678`
19
- - a small proxy/health server on port `7861` for HF Spaces
20
- - periodic backup of `/home/node/.n8n` to a private Hugging Face Dataset
 
 
 
 
 
 
 
21
 
22
- ## Required secret
23
 
24
- - `HF_TOKEN`: Hugging Face token with write access to create/update a private dataset backup
 
 
 
 
 
 
 
25
 
26
- ## Recommended variables
27
 
28
- - `BACKUP_DATASET_NAME`: backup dataset name. Default: `hugging8n-backup`
29
- - `SYNC_INTERVAL`: backup interval in seconds. Default: `180`
30
- - `GENERIC_TIMEZONE`: timezone for schedule triggers. Example: `Asia/Dhaka`
31
- - `N8N_ENCRYPTION_KEY`: optional explicit encryption key. If omitted, n8n stores it inside `.n8n` and the backup preserves it
32
- - `N8N_BASIC_AUTH_ACTIVE`: set to `true` if you want built-in basic auth
33
- - `N8N_BASIC_AUTH_USER`: basic auth username
34
- - `N8N_BASIC_AUTH_PASSWORD`: basic auth password
35
 
36
- ## Optional variables
37
 
38
- - `HF_USERNAME`: owner of the backup dataset. By default this is inferred from `SPACE_AUTHOR_NAME`
39
- - `SPACE_HOST_OVERRIDE`: set this only if you want to override the detected Space hostname
40
- - `N8N_DIAGNOSTICS_ENABLED=false`
41
- - `N8N_PERSONALIZATION_ENABLED=false`
42
 
43
- ## How persistence works
44
 
45
- On startup, the Space restores `/home/node/.n8n` from a private dataset repo.
46
 
47
- While running, it watches for changes and uploads the updated `.n8n` directory back to the dataset. This preserves:
48
 
49
- - workflows
50
- - credentials
51
- - users
52
- - SQLite database
53
- - encryption key
54
 
55
- ## Keep-alive
56
 
57
- If you already solved the sleep problem in your HF setup, use that. If not, `setup-uptimerobot.sh` can create an external monitor for `https://<your-space>.hf.space/health`.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
  colorTo: indigo
6
  sdk: docker
7
  app_port: 7861
8
+ pinned: true
9
  license: mit
10
  ---
11
 
12
+ <!-- Badges -->
13
+ [![GitHub Stars](https://img.shields.io/github/stars/somratpro/hugging8n?style=flat-square)](https://github.com/somratpro/Hugging8N)
14
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=flat-square)](https://opensource.org/licenses/MIT)
15
+ [![HF Space](https://img.shields.io/badge/πŸ€—%20HuggingFace-Space-blue?style=flat-square)](https://huggingface.co/spaces/somratpro/Hugging8n)
16
+ [![n8n](https://img.shields.io/badge/n8n-workflow%20automation-orange?style=flat-square)](https://n8n.io)
17
 
18
+ **Self-hosted n8n workflow automation β€” free, no server needed.** Hugging8n runs [n8n](https://n8n.io) on HuggingFace Spaces Docker, giving you a full-featured workflow automation platform with 400+ integrations. Your workflows, credentials, and settings are automatically backed up to a private HuggingFace Dataset so nothing is lost on restart.
19
 
20
+ ## Table of Contents
21
 
22
+ - [✨ Features](#-features)
23
+ - [πŸš€ Quick Start](#-quick-start)
24
+ - [πŸ” Authentication](#-authentication)
25
+ - [πŸ’Ύ Persistent Backup](#-persistent-backup)
26
+ - [πŸ’“ Staying Alive](#-staying-alive)
27
+ - [πŸ—οΈ Architecture](#-architecture)
28
+ - [πŸ’» Local Development](#-local-development)
29
+ - [πŸ› Troubleshooting](#-troubleshooting)
30
+ - [🀝 Contributing](#-contributing)
31
+ - [πŸ“„ License](#-license)
32
 
33
+ ## ✨ Features
34
 
35
+ - ⚑ **Zero Config:** Duplicate this Space, set your credentials, and n8n is running in minutes.
36
+ - πŸ”Œ **400+ Integrations:** Connect any service β€” HTTP, webhooks, databases, Slack, Gmail, GitHub, and more.
37
+ - πŸ’Ύ **Persistent Backup:** Workflows, credentials, and the SQLite database back up automatically to a private HF Dataset. Restored on every startup so nothing is lost.
38
+ - πŸ” **Basic Auth:** n8n is protected by basic auth out of the box β€” just set your username and password.
39
+ - 🐳 **Docker Native:** Runs on the free HF Spaces tier (2 vCPU, 16GB RAM) with SQLite β€” no external database needed.
40
+ - ⏰ **External Keep-Alive:** Optional UptimeRobot integration to prevent free Space sleep.
41
+ - 🌐 **Health Endpoint:** `/health` returns service and sync status for monitoring.
42
+ - 🏠 **100% HF-Native:** Runs entirely on HuggingFace's free infrastructure.
43
 
44
+ ## πŸš€ Quick Start
45
 
46
+ ### Step 1: Duplicate this Space
 
 
 
 
 
 
47
 
48
+ [![Duplicate this Space](https://huggingface.co/datasets/huggingface/badges/resolve/main/duplicate-this-space-xl.svg)](https://huggingface.co/spaces/somratpro/Hugging8n?duplicate=true)
49
 
50
+ Click the button above to duplicate the template into your own account.
 
 
 
51
 
52
+ ### Step 2: Add Your Secrets
53
 
54
+ Navigate to your new Space's **Settings**, scroll to the **Variables and secrets** section, and add the following under **Secrets**:
55
 
56
+ #### Required β€” Authentication
57
 
58
+ | Secret | Description |
59
+ | :--- | :--- |
60
+ | `N8N_BASIC_AUTH_PASSWORD` | Password to log in to your n8n instance. Set this to protect your workflows. |
 
 
61
 
62
+ #### Required β€” Persistent Backup *(Highly Recommended)*
63
 
64
+ | Secret | Description |
65
+ | :--- | :--- |
66
+ | `HF_TOKEN` | HuggingFace token with write access. Get one at [hf.co/settings/tokens](https://huggingface.co/settings/tokens). |
67
+
68
+ > [!TIP]
69
+ > Without `HF_TOKEN`, n8n will still run, but workflows and credentials will be **lost every time the Space restarts**. It is strongly recommended to set this.
70
+
71
+ #### Optional β€” Configuration
72
+
73
+ | Variable / Secret | Default | Description |
74
+ | :--- | :--- | :--- |
75
+ | `N8N_BASIC_AUTH_USER` | `admin` | Username for n8n login |
76
+ | `HF_USERNAME` | *(auto-detected)* | Your HF username, for naming the backup dataset |
77
+ | `BACKUP_DATASET_NAME` | `hugging8n-backup` | Name of the private dataset repo for backup |
78
+ | `SYNC_INTERVAL` | `180` | How often to back up, in seconds |
79
+ | `GENERIC_TIMEZONE` | `UTC` | Timezone for schedule triggers (e.g. `Asia/Dhaka`) |
80
+ | `N8N_ENCRYPTION_KEY` | *(auto-generated)* | Encryption key for stored credentials. Set explicitly so it survives Space rebuilds. |
81
+
82
+ #### Build-Time Variable (add as Variable, not Secret)
83
+
84
+ | Variable | Default | Description |
85
+ | :--- | :--- | :--- |
86
+ | `N8N_VERSION` | `latest` | Pin a specific n8n version (e.g. `1.90.0`) for reproducibility |
87
+
88
+ > [!IMPORTANT]
89
+ > On HuggingFace Spaces, `N8N_VERSION` must be added as a **Variable** (not a Secret) so it is passed as a Docker build arg during image build.
90
+
91
+ ### Step 3: Deploy & Run
92
+
93
+ That's it! The Space will build and start automatically. Watch progress in the **Logs** tab. First build takes a few minutes as n8n installs.
94
+
95
+ ### Step 4: Log In
96
+
97
+ Once the Space is running, open it and log in with:
98
+ - **Username:** the value of `N8N_BASIC_AUTH_USER` (default: `admin`)
99
+ - **Password:** the value of `N8N_BASIC_AUTH_PASSWORD`
100
+
101
+ > [!WARNING]
102
+ > If you did not set `N8N_BASIC_AUTH_PASSWORD`, your n8n instance is **unprotected**. Anyone with the Space URL can access your workflows and credentials. Set this secret immediately.
103
+
104
+ ## πŸ” Authentication
105
+
106
+ Hugging8n uses n8n's built-in basic auth to protect your instance. It is enabled by default.
107
+
108
+ | Variable | Default | Description |
109
+ | :--- | :--- | :--- |
110
+ | `N8N_BASIC_AUTH_ACTIVE` | `true` | Set to `false` to disable basic auth (not recommended) |
111
+ | `N8N_BASIC_AUTH_USER` | `admin` | Login username |
112
+ | `N8N_BASIC_AUTH_PASSWORD` | *(none)* | Login password β€” **must be set** |
113
+
114
+ ## πŸ’Ύ Persistent Backup
115
+
116
+ Hugging8n automatically backs up your entire n8n data directory (`/home/node/.n8n`) to a **private** HuggingFace Dataset.
117
+
118
+ **What is backed up:**
119
+ - All workflows
120
+ - All credentials (encrypted)
121
+ - SQLite database (hot-copy via `sqlite3 .backup`)
122
+ - n8n encryption key
123
+ - User data
124
+
125
+ **How it works:**
126
+ 1. On startup: restore from dataset (if it exists)
127
+ 2. Every `SYNC_INTERVAL` seconds: detect changes and upload
128
+ 3. On shutdown (`SIGTERM`): run a final backup before exiting
129
+
130
+ | Variable | Default | Description |
131
+ | :--- | :--- | :--- |
132
+ | `HF_TOKEN` | β€” | HF write token |
133
+ | `HF_USERNAME` | *(auto)* | Dataset owner username |
134
+ | `BACKUP_DATASET_NAME` | `hugging8n-backup` | Dataset repo name |
135
+ | `SYNC_INTERVAL` | `180` | Backup interval in seconds |
136
+
137
+ > [!TIP]
138
+ > Set `N8N_ENCRYPTION_KEY` explicitly. If n8n auto-generates it and the Space is rebuilt (not just restarted), the key will be different and your backed-up credentials will be unreadable.
139
+
140
+ ## πŸ’“ Staying Alive *(Recommended on Free HF Spaces)*
141
+
142
+ Free HF Spaces sleep after periods of inactivity. Set up an external UptimeRobot monitor to keep yours awake.
143
+
144
+ 1. Create a free account at [uptimerobot.com](https://uptimerobot.com)
145
+ 2. Get your **Main API Key** from My Settings β†’ API Settings
146
+ 3. Run the helper script:
147
+ ```bash
148
+ UPTIMEROBOT_API_KEY=your-key ./setup-uptimerobot.sh your-space.hf.space
149
+ ```
150
+ 4. UptimeRobot will ping `/health` every 5 minutes from outside HF, keeping the Space awake.
151
+
152
+ > [!NOTE]
153
+ > This works for **public** Spaces only. Private Spaces cannot be pinged by external monitors.
154
+
155
+ ## πŸ—οΈ Architecture
156
+
157
+ ```
158
+ Hugging8n/
159
+ β”œβ”€β”€ Dockerfile # Builds on node:22-slim, installs n8n + Python sync
160
+ β”œβ”€β”€ start.sh # Startup orchestrator: restore β†’ sync loop β†’ proxy β†’ n8n
161
+ β”œβ”€β”€ n8n-sync.py # Backup/restore via huggingface_hub
162
+ β”œβ”€β”€ health-server.js # HTTP + WebSocket reverse proxy (port 7861 β†’ 5678)
163
+ β”œβ”€β”€ setup-uptimerobot.sh # One-shot UptimeRobot monitor creation
164
+ β”œβ”€β”€ .env.example # All environment variable documentation
165
+ └── README.md # This file
166
+ ```
167
+
168
+ **Startup sequence:**
169
+ 1. Read environment variables and set n8n config
170
+ 2. Warn if `N8N_BASIC_AUTH_PASSWORD` is not set
171
+ 3. Restore backup from HF Dataset (if `HF_TOKEN` is set)
172
+ 4. Start backup sync loop in background
173
+ 5. Start health/proxy server on port 7861
174
+ 6. Start n8n on port 5678
175
+ 7. On `SIGTERM` / `SIGINT`: final backup + clean exit
176
+
177
+ ## πŸ’» Local Development
178
+
179
+ ```bash
180
+ git clone https://github.com/somratpro/Hugging8N.git
181
+ cd Hugging8N
182
+ cp .env.example .env
183
+ # Fill in N8N_BASIC_AUTH_PASSWORD and optionally HF_TOKEN
184
+ ```
185
+
186
+ **With Docker:**
187
+
188
+ ```bash
189
+ docker build -t hugging8n .
190
+ docker run -p 7861:7861 --env-file .env hugging8n
191
+ ```
192
+
193
+ Then open `http://localhost:7861`.
194
+
195
+ **Pin an n8n version:**
196
+
197
+ ```bash
198
+ docker build --build-arg N8N_VERSION=1.90.0 -t hugging8n .
199
+ ```
200
+
201
+ ## πŸ› Troubleshooting
202
+
203
+ - **Can't log in:** Make sure `N8N_BASIC_AUTH_PASSWORD` is set in Secrets. Default username is `admin`.
204
+ - **Workflows lost after restart:** Set `HF_TOKEN` and `HF_USERNAME` so the backup dataset is created and restored.
205
+ - **n8n editor shows "disconnected":** The WebSocket proxy may not have connected yet β€” wait a few seconds and refresh. Check Space logs for errors.
206
+ - **Space keeps sleeping:** Use `setup-uptimerobot.sh` to set up an external keep-alive monitor.
207
+ - **Credentials unreadable after rebuild:** Make sure `N8N_ENCRYPTION_KEY` is set explicitly as a Secret. If it was auto-generated, it changes on rebuild.
208
+ - **Build fails:** If you pinned `N8N_VERSION`, verify the version exists at [npmjs.com/package/n8n](https://www.npmjs.com/package/n8n?activeTab=versions).
209
+ - **Backup failing:** Check Space logs for `Sync failed`. Verify `HF_TOKEN` has write access and `HF_USERNAME` is correct.
210
+
211
+ ## 🀝 Contributing
212
+
213
+ Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
214
+
215
+ ## πŸ“„ License
216
+
217
+ MIT β€” see [LICENSE](LICENSE) for details.
218
+
219
+ *Made with ❀️ by [@somratpro](https://github.com/somratpro)*
SECURITY.md ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Security Policy
2
+
3
+ ## Reporting a Vulnerability
4
+
5
+ If you discover a security vulnerability, please report it responsibly:
6
+
7
+ 1. **Do NOT open a public issue**
8
+ 2. Email the maintainer or open a private security advisory on GitHub
9
+ 3. Include steps to reproduce if possible
10
+
11
+ We'll respond within 48 hours and work on a fix.
12
+
13
+ ## Security Best Practices
14
+
15
+ When deploying Hugging8n:
16
+
17
+ - **Enable basic auth** β€” set `N8N_BASIC_AUTH_USER` and `N8N_BASIC_AUTH_PASSWORD` to protect your n8n instance from unauthorized access
18
+ - **Use a strong password** β€” generate with `openssl rand -base64 24`
19
+ - **Set your Space to Private** β€” prevents unauthorized access to your n8n instance from the web
20
+ - **Keep your HF token scoped** β€” use fine-grained tokens with minimum permissions (read/write to your backup dataset only)
21
+ - **Set a strong `N8N_ENCRYPTION_KEY`** β€” protects your stored credentials; if lost, credentials cannot be recovered
22
+ - **Don't commit `.env` files** β€” the `.gitignore` already excludes them
23
+ - **Review n8n credentials** β€” periodically audit credentials stored in n8n
24
+
25
+ ## Supported Versions
26
+
27
+ | Version | Supported |
28
+ |---------|-----------|
29
+ | 1.0.x | βœ… |
health-server.js CHANGED
@@ -75,21 +75,33 @@ const server = http.createServer((req, res) => {
75
 
76
  server.on("upgrade", (req, socket, head) => {
77
  const upstream = net.connect(TARGET_PORT, TARGET_HOST, () => {
78
- socket.write(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  `${req.method} ${req.url} HTTP/${req.httpVersion}\r\n` +
80
- Object.entries(buildHeaders(req))
81
- .map(([key, value]) => `${key}: ${value}`)
82
- .join("\r\n") +
83
  "\r\n\r\n",
84
  );
 
85
  if (head && head.length) upstream.write(head);
86
  upstream.pipe(socket);
87
  socket.pipe(upstream);
88
  });
89
 
90
- upstream.on("error", () => {
91
- socket.destroy();
92
- });
93
  });
94
 
95
  server.listen(PUBLIC_PORT, "0.0.0.0", () => {
 
75
 
76
  server.on("upgrade", (req, socket, head) => {
77
  const upstream = net.connect(TARGET_PORT, TARGET_HOST, () => {
78
+ const headers = {
79
+ ...req.headers,
80
+ host: `${TARGET_HOST}:${TARGET_PORT}`,
81
+ "x-forwarded-for": req.socket.remoteAddress || "",
82
+ "x-forwarded-host": req.headers.host || "",
83
+ "x-forwarded-proto": req.headers["x-forwarded-proto"] || "https",
84
+ upgrade: req.headers.upgrade || "websocket",
85
+ connection: "Upgrade",
86
+ };
87
+
88
+ const headerLines = Object.entries(headers)
89
+ .map(([key, value]) => `${key}: ${value}`)
90
+ .join("\r\n");
91
+
92
+ upstream.write(
93
  `${req.method} ${req.url} HTTP/${req.httpVersion}\r\n` +
94
+ headerLines +
 
 
95
  "\r\n\r\n",
96
  );
97
+
98
  if (head && head.length) upstream.write(head);
99
  upstream.pipe(socket);
100
  socket.pipe(upstream);
101
  });
102
 
103
+ upstream.on("error", () => socket.destroy());
104
+ socket.on("error", () => upstream.destroy());
 
105
  });
106
 
107
  server.listen(PUBLIC_PORT, "0.0.0.0", () => {
n8n-sync.py CHANGED
@@ -122,7 +122,6 @@ def restore() -> bool:
122
  repo_type="dataset",
123
  token=HF_TOKEN,
124
  local_dir=tmpdir,
125
- local_dir_use_symlinks=False,
126
  )
127
 
128
  tmp_path = Path(tmpdir)
 
122
  repo_type="dataset",
123
  token=HF_TOKEN,
124
  local_dir=tmpdir,
 
125
  )
126
 
127
  tmp_path = Path(tmpdir)
start.sh CHANGED
@@ -20,7 +20,9 @@ export N8N_PORT
20
  export N8N_PROTOCOL="${N8N_PROTOCOL:-https}"
21
  export N8N_PROXY_HOPS="${N8N_PROXY_HOPS:-1}"
22
  export N8N_LISTEN_ADDRESS="${N8N_LISTEN_ADDRESS:-0.0.0.0}"
23
- export N8N_SECURE_COOKIE="${N8N_SECURE_COOKIE:-true}"
 
 
24
  export N8N_DIAGNOSTICS_ENABLED="${N8N_DIAGNOSTICS_ENABLED:-false}"
25
  export N8N_PERSONALIZATION_ENABLED="${N8N_PERSONALIZATION_ENABLED:-false}"
26
  export N8N_USER_FOLDER="$N8N_HOME"
@@ -28,6 +30,17 @@ export N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS="${N8N_ENFORCE_SETTINGS_FILE_PERMIS
28
  export GENERIC_TIMEZONE="${GENERIC_TIMEZONE:-${TZ:-UTC}}"
29
  export TZ="${TZ:-$GENERIC_TIMEZONE}"
30
 
 
 
 
 
 
 
 
 
 
 
 
31
  echo ""
32
  echo " ╔════════════════════════════════════╗"
33
  echo " β•‘ Hugging8n β•‘"
 
20
  export N8N_PROTOCOL="${N8N_PROTOCOL:-https}"
21
  export N8N_PROXY_HOPS="${N8N_PROXY_HOPS:-1}"
22
  export N8N_LISTEN_ADDRESS="${N8N_LISTEN_ADDRESS:-0.0.0.0}"
23
+ # Must be false: HF Spaces terminates TLS at its edge; n8n sees plain HTTP internally.
24
+ # Secure cookies require HTTPS end-to-end and will break login on HF Spaces.
25
+ export N8N_SECURE_COOKIE="${N8N_SECURE_COOKIE:-false}"
26
  export N8N_DIAGNOSTICS_ENABLED="${N8N_DIAGNOSTICS_ENABLED:-false}"
27
  export N8N_PERSONALIZATION_ENABLED="${N8N_PERSONALIZATION_ENABLED:-false}"
28
  export N8N_USER_FOLDER="$N8N_HOME"
 
30
  export GENERIC_TIMEZONE="${GENERIC_TIMEZONE:-${TZ:-UTC}}"
31
  export TZ="${TZ:-$GENERIC_TIMEZONE}"
32
 
33
+ # Basic auth β€” enabled by default to protect your n8n instance
34
+ export N8N_BASIC_AUTH_ACTIVE="${N8N_BASIC_AUTH_ACTIVE:-true}"
35
+ if [ "${N8N_BASIC_AUTH_ACTIVE}" = "true" ]; then
36
+ export N8N_BASIC_AUTH_USER="${N8N_BASIC_AUTH_USER:-admin}"
37
+ export N8N_BASIC_AUTH_PASSWORD="${N8N_BASIC_AUTH_PASSWORD:-}"
38
+ if [ -z "${N8N_BASIC_AUTH_PASSWORD:-}" ]; then
39
+ echo "⚠️ WARNING: N8N_BASIC_AUTH_ACTIVE=true but N8N_BASIC_AUTH_PASSWORD is not set."
40
+ echo " Your n8n instance is NOT protected. Set N8N_BASIC_AUTH_PASSWORD in Secrets."
41
+ fi
42
+ fi
43
+
44
  echo ""
45
  echo " ╔════════════════════════════════════╗"
46
  echo " β•‘ Hugging8n β•‘"