All apps · 0 apps
DumbPad
Docker app from ZappyZap's Repository
Overview
Readme
View on GitHubDumbPad
A stupid simple, no auth (unless you want it!), modern notepad application with auto-save functionality and dark mode support.
Table of Contents
- Features
- Quick Start
- Important: Docker Permissions
- Configuration
- Security
- Technical Details
- Links
- Contributing
- Future Features
Features
- Simple, clean interface
- Auto-saving
- Dark mode support
- Responsive design
- Docker support
- Optional PIN protection (4-10 digits)
- File-based storage
- Data persistence across updates
- Markdown Formatting with enhanced support
- GitHub-style alert blocks (Note, Tip, Important, Warning, Caution)
- Extended table formatting
- Auto-expand collapsible details in print (configurable)
- Code syntax highlighting in
fenced codeblocks
- Direct notepad linking with URL parameters
- Copy shareable notepad links
- Browser navigation support (back/forward buttons)
- Fuzzy Search (by filename and file contents)
- PWA Support with automatic cache updates
Quick Start
Prerequisites
- Docker (recommended)
- Node.js >=20.0.0 (for local development)
Option 1: Docker (For Dummies)
# Pull and run with one command
docker run -p 3000:3000 \
-v ./data:/app/data \
dumbwareio/dumbpad:latest
- Go to http://localhost:3000
- Start typing - Your notes auto-save
- Marvel at how dumb easy this was
⚠️ Note: If the container crashes with permission errors, see Docker Permissions section below.
Option 2: Docker Compose (For Dummies who like customizing)
Create a docker-compose.yml file:
services:
dumbpad:
image: dumbwareio/dumbpad:latest
container_name: dumbpad
restart: unless-stopped
ports:
- ${DUMBPAD_PORT:-3000}:3000
volumes:
- ${DUMBPAD_DATA_PATH:-./data}:/app/data
environment:
# The title shown in the web interface
SITE_TITLE: ${DUMBPAD_SITE_TITLE:-DumbPad}
# Optional PIN protection (leave empty to disable)
DUMBPAD_PIN: ${DUMBPAD_PIN:-}
# The base URL for the application
BASE_URL: ${DUMBPAD_BASE_URL:-http://localhost:3000} # Use ALLOWED_ORIGINS below to restrict cors to specific origins
# (OPTIONAL)
# Usage: Comma-separated list of urls: http://localhost:port,http://internalip:port,https://base.proxy.tld,https://authprovider.domain.tld
# ALLOWED_ORIGINS: ${DUMBPAD_ALLOWED_ORIGINS:-http://localhost:3000} # Comment out to allow all origins (*)
# LOCKOUT_TIME: ${DUMBPAD_LOCK_TIME:-15} # Customize pin lockout time (if empty, defaults to 15 in minutes)
# MAX_ATTEMPTS: ${DUMBPAD_MAX_ATTEMPTS:-5} # Customize pin max attempts (if empty, defaults to 5)
# COOKIE_MAX_AGE: ${DUMBPAD_COOKIE_MAX_AGE:-24} # Customize maximum age of cookies primarily used for pin verification (default 24) in hours
# PAGE_HISTORY_COOKIE_AGE: ${DUMBPAD_PAGE_HISTORY_COOKIE_AGE:-365} # Customize age of cookie to show the last notepad opened (default 365 | max 400) in days - shows default notepad on load if expired
# MARKDOWN CODE SYNTAX HIGHLIGHTING (only use below if you want to restrict to specific languages):
# By default, DumbPad includes support for all ~180 languages supported by highlight.js.
# view entire list and usage in /docs/MARKDOWN_SYNTAX_HIGHLIGHTING_USAGE.md
# HIGHLIGHT_LANGUAGES=c,csharp,css,dockerfile,go,html,java,javascript,json,kotlin,markdown,perl,php,python,ruby,sql,swift,typescript,xml,yaml
Then run:
docker compose up -d
- Go to http://localhost:3000
- Start typing - Your notes auto-save
- Rejoice in the glory of your dumb notes
⚠️ Note: If the container crashes with permission errors, see Docker Permissions section below.
Option 3: Running Locally (For Developers)
- Install dependencies:
npm install
- Set environment variables in
.envorcp .env.example .env:
PORT=3000 # Port to run the server on
DUMBPAD_PIN=1234 # Optional PIN protection
SITE_TITLE=DumbPad # Custom site title
BASE_URL=http://localhost:3000 # Base URL for the application
- Start the server:
npm start
Windows Users
If you're using Windows PowerShell with Docker, use this format for paths:
docker run -p 3000:3000 -v "${PWD}\data:/app/data" dumbwareio/dumbpad:latest
Upgrading from Previous Versions
⚠️ Important: Docker Permission Issues (New Installations & Upgrades)
As of PR #76, DumbPad now runs as a non-root user (UID 1000) inside the Docker container for improved security. This can cause permission issues in two scenarios:
- Upgrading from a previous version - Existing data directory may have incorrect permissions, causing notepads to appear blank (Issue #74)
- Fresh installation - Docker may create the data directory with host user permissions that don't match UID 1000, causing container restart loops with
EACCES: permission deniederrors (Issue #79)
Symptoms
- Fresh installations: Container crashes on startup with
Error: EACCES: permission denied, open '/app/data/notepads.json' - Upgrades: Previously saved notepads appear blank or empty
Solution
Option 1: Fix Existing Installation
Set the ownership of your data directory to match the container's non-root user (UID 1000):
Linux/macOS:
# Stop the container first
docker stop dumbpad
# Fix permissions (replace /path/to/your/data with your actual path)
sudo chown -R 1000:1000 /path/to/your/data
Example for common setups:
# If using the default ./data directory
sudo chown -R 1000:1000 ./data
# If using a custom path like /opt/docker/dumbpad
sudo chown -R 1000:1000 /opt/docker/dumbpad
# For Unraid users
sudo chown -R 1000:1000 /mnt/user/appdata/dumbpad
Windows (Docker Desktop):
# Windows users typically don't need to change permissions
# Docker Desktop handles volume permissions automatically
Option 2: Preventive Setup (Fresh Installations)
For new installations, create the data directory with correct permissions before starting the container:
Linux/macOS:
# Create data directory
mkdir -p ./data
# Set correct ownership
sudo chown -R 1000:1000 ./data
# Now start the container
docker compose up -d
Windows (Docker Desktop):
# No special setup needed - Docker Desktop handles permissions automatically
docker compose up -d
Verifying the Fix
After updating permissions, verify everything is working:
Start/Restart the container:
docker restart dumbpad # or if starting fresh docker compose up -dCheck container logs (should start without errors):
docker logs dumbpadVerify file ownership inside container:
docker exec dumbpad ls -la /app/dataYou should see files owned by
nodeor UID1000Test the application by accessing http://localhost:3000 and creating a test notepad
Why This Change?
Running containers as non-root users is a security best practice that:
- Limits potential damage from container escapes
- Reduces attack surface
- Aligns with security compliance standards
Features
- 📝 Auto-saving notes
- 🌓 Dark/Light mode support
- 🔒 Optional PIN protection
- 📱 Mobile-friendly interface / PWA Support
- 🗂️ Multiple notepads
- 📄 Enhanced Markdown Formatting with GitHub-style alerts and extended tables
- 🔗 Direct notepad linking with shareable URLs
- 🧭 Browser navigation support (back/forward buttons)
- ⬇️ Download notes as text or markdown files
- 🖨️ Print functionality with auto-expanded collapsible sections
- 🔍 Fuzzy Search by name or contents
- 🔄 Real-time saving
- 💽 Add .txt files into data folder to import (requires page refresh)
- ⚡ Zero dependencies on client-side
- 🛡️ Built-in security features
- 🎨 Clean, modern interface
- 📦 Docker support with easy configuration
- 🌐 Optional CORS support
- ⚙️ Customizable settings
- 🔄 Automatic cache updates and version management
Configuration
Environment Variables
| Variable | Description | Default | Required |
|---|---|---|---|
| PORT | Server port | 3000 | No |
| BASE_URL | Base URL for the application | http://localhost:PORT | Yes |
| DUMBPAD_PIN | PIN protection (4-10 digits) | None | No |
| SITE_TITLE | Site title displayed in header | DumbPad | No |
| NODE_ENV | Node environment mode (development or production) | production | No |
| ALLOWED_ORIGINS | Allowed CORS origins (* for all or comma-separated list) |
* | No |
| LOCKOUT_TIME | Lockout time after max PIN attempts (in minutes) | 15 | No |
| MAX_ATTEMPTS | Maximum PIN entry attempts before lockout | 5 | No |
| COOKIE_MAX_AGE | Maximum age of authentication cookies (in hours) | 24 | No |
| PAGE_HISTORY_COOKIE_AGE | Age of cookie storing last opened notepad (in days, max 400) | 365 | No |
| TRUST_PROXY | Enable proxy trust for X-Forwarded-For headers | false | No |
| TRUSTED_PROXY_IPS | Comma-separated list of trusted proxy IPs | None | No |
| HIGHLIGHT_LANGUAGES | Comma-separated list of code syntax languages to restrict to | all if not supplied | No |
Proxy Trust Configuration
When deploying DumbPad behind a reverse proxy (nginx, Apache, Cloudflare, etc.), you may need to configure proxy trust to correctly identify client IP addresses for rate-limiting and authentication.
⚠️ Security Warning
By default, TRUST_PROXY is false (most secure). Only enable proxy trust if you're deploying behind a trusted reverse proxy. Incorrect configuration can allow attackers to bypass rate-limiting and authentication by spoofing the X-Forwarded-For header.
When to Enable Proxy Trust
Enable TRUST_PROXY=true only if:
- You're deploying behind a reverse proxy (nginx, Cloudflare, etc.)
- The proxy adds
X-Forwarded-Forheaders - You can explicitly list all trusted proxy IPs in
TRUSTED_PROXY_IPS
Configuration Examples
Example 1: Behind nginx on the same host
TRUST_PROXY=true
TRUSTED_PROXY_IPS=127.0.0.1
Example 2: Docker with nginx reverse proxy
TRUST_PROXY=true
TRUSTED_PROXY_IPS=172.17.0.1 # Docker default gateway IP
Example 3: Multiple proxies (load balancer + nginx)
TRUST_PROXY=true
TRUSTED_PROXY_IPS=10.0.0.1,10.0.0.2 # IPs of both proxies
Example 4: Cloudflare (using Cloudflare IPs)
TRUST_PROXY=true
# List all Cloudflare IP ranges that connect to your origin
# See: https://www.cloudflare.com/ips/
TRUSTED_PROXY_IPS=173.245.48.0,103.21.244.0,103.22.200.0,...
Finding Your Proxy IP
To find your proxy's IP address:
Docker:
docker network inspect bridge | grep Gateway
Check incoming connections:
# While DumbPad is running, check who's connecting
netstat -tn | grep :3000
How It Works
- When
TRUST_PROXY=false(default): Always uses the direct socket IP address, ignoringX-Forwarded-Forheaders - When
TRUST_PROXY=truewithTRUSTED_PROXY_IPS: Validates the immediate connecting IP against the trusted list before trustingX-Forwarded-For - When
TRUST_PROXY=truewithoutTRUSTED_PROXY_IPS: TrustsX-Forwarded-Forfrom any source (⚠️ not recommended for production)
Security
Features
- Variable-length PIN support (4-10 digits)
- Constant-time PIN comparison
- Brute force protection:
- 5 attempts maximum
- 15-minute lockout after failed attempts
- IP-based tracking with spoofing protection
- Validated client IP extraction (ignores untrusted X-Forwarded-For by default)
- Secure cookie handling
- No client-side PIN storage
- Rate limiting
- Collaborative editing
- CORS support for origin restrictions (optional)
- Configurable proxy trust with IP validation
User Settings
Access settings via the gear icon (⚙️) in the header or use keyboard shortcut:
- Windows/Linux:
Ctrl+Alt+, - macOS:
Cmd+Ctrl+,
Available Settings
| Setting | Description | Default | Options |
|---|---|---|---|
| Auto-save Status Interval | Time interval for auto-save notifications (0 = disabled) | 1000ms | Any number (milliseconds) |
| Remote Connection Messages | Show notifications when users connect/disconnect | Enabled | Enabled/Disabled |
| Disable Print Expansion | Prevent auto-expanding collapsed sections when printing | Disabled | Enabled/Disabled |
| Default Markdown Preview | Default view when loading DumbPad (Client-based) | Editor | Editor, Split, Full |
Notepad Management
- Unique Names: Notepad names are automatically made unique by the server. If you try to create or rename a notepad with an existing name, the server will append a suffix (e.g., "Note-1", "Note-2")
- Name Validation: The server handles all name validation and uniqueness checks. The frontend will display a notification if your requested name was modified
- Auto-save: Changes are automatically saved every 300ms after you stop typing, with periodic saves every 2 seconds
- Persistence: All settings are stored in your browser's local storage and persist across sessions
Technical Details
Stack
- Backend: Node.js (>=20.0.0) with Express
- Frontend: Vanilla JavaScript (ES6+) with enhanced markdown support
- Container: Docker with multi-stage builds
- Security: Express security middleware
- Storage: File-based with auto-save
- Theme: Dynamic dark/light mode with system preference support
- PWA: Service Worker with automatic cache updates and version management
- Markdown: Enhanced with alert blocks, extended tables, and collapsible content
- Real-time: WebSocket-based collaboration and live updates
- Navigation: SPA-style routing with shareable URLs and browser history support
- Print: Advanced print preview with auto-expanding collapsible content and theme preservation
Dependencies
- express: Web framework
- cors: Cross-origin resource sharing
- dotenv: Environment configuration
- cookie-parser: Cookie handling
- express-rate-limit: Rate limiting
- marked: Markdown formatting
- marked-alert: GitHub-style alert blocks for markdown
- marked-extended-tables: Enhanced table support for markdown
- marked-highlight: Syntax highlighting for code blocks in markdown
- @highlightjs/cdn-assets: Highlight.js assets for code syntax highlighting
- fuse.js: Fuzzy searching
- ws: WebSocket support for real-time collaboration
The data directory contains:
notepads.json: List of all notepads- Individual
.txtfiles for each notepad's content - Drop in .txt files to import notes (requires page refresh)
⚠️ Important: Never delete the data directory when updating! This is where all your notes are stored.
Usage
Basic Operations
- Start typing: Notes auto-save as you type (every 300ms after stopping, with periodic saves every 2 seconds)
- Theme toggle: Switch between light/dark mode with the toggle button
- Force save:
Ctrl+S(orCmd+Son Mac) - Search:
Ctrl+K(orCmd+K) to open fuzzy search across all notepads - Copy link: Click the link button (🔗) to copy the current notepad's shareable URL
- Settings: Click the gear icon (⚙️) or use
Ctrl+Alt+,(orCmd+Ctrl+,)
Notepad Management
- Create: Click the + button or
Ctrl+Alt+N(orCmd+Ctrl+N) - Rename: Click rename button or
Ctrl+Alt+R(orCmd+Ctrl+R) - Delete: Click delete button or
Ctrl+Alt+X(orCmd+Ctrl+X) - Navigate: Use dropdown, arrow keys (
Ctrl+Alt+↑/↓), or browser back/forward buttons - Download: Click download button or
Ctrl+Alt+A(orCmd+Ctrl+A) for .txt/.md export - Print:
Ctrl+P(orCmd+P) with enhanced formatting and auto-expanded collapsible sections
Preview Modes
Swap between different modes using the 3-way markdown toggle button: (Editor, Split, Full)
| Editor | Split Preview | Full Preview |
|---|---|---|
You can also set your default preview mode in settings.
Markdown Formatting
DumbPad now supports enhanced markdown features:
GitHub-Style Alert Blocks
> [!NOTE]
> This is a note alert block
> [!TIP]
> This is a tip alert block
> [!IMPORTANT]
> This is an important alert block
> [!WARNING]
> This is a warning alert block
> [!CAUTION]
> This is a caution alert block
Extended Table Support
- Advanced table formatting with alignment
- Enhanced styling for better readability
Collapsible Details
<details>
<summary>Click to expand</summary>
Content that will be automatically expanded when printing
</details>
Code Syntax Highlighting
- Uses highlight.js for syntax highlighting using fenced code blocks
- Defaults to all supported languages (configured via
HIGHLIGHT_LANGUAGESenvironment variable if you would like to restrict to specific languages) - Read more and view examples in /docs/MARKDOWN_SYNTAX_HIGHLIGHTING_USAGE.md
```javascript
console.log("Hello, world!");
```
URL Parameters
- Direct notepad linking:
?id=notepadname- Opens a specific notepad by name (case-insensitive) - Browser navigation: Use back/forward buttons to navigate between notepads
- Shareable URLs: Copy links to share specific notepads with others
Technical Details
- Backend: Node.js with Express
- Frontend: Vanilla JavaScript
- Storage: File-based storage in
datadirectory - Styling: Modern CSS with CSS variables for theming
- Security: Constant-time PIN comparison, brute force protection
Links
- GitHub: github.com/dumbwareio/dumbpad
- Docker Hub: hub.docker.com/r/dumbwareio/dumbpad
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes using conventional commits
- Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
See Development Guide for local setup and guidelines.
Made with ❤️ by DumbWare.io
🌐 Check Us Out
- Website: dumbware.io
- Join the Chaos: Discord 💬
Support the Project
Future Features
- File attachments
- Markdown code syntax highlighting
Got an idea? Open an issue or submit a PR
Install DumbPad on Unraid in a few clicks.
Find DumbPad in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.
Categories
Download Statistics
Total Downloads Over Time
Related apps
Explore more like this
Explore allLinks
Details
dumbwareio/dumbpad:latestRuntime arguments
- Web UI
http://[IP]:[PORT:3000]- Network
bridge- Shell
sh- Privileged
- false
Template configuration
The port on which the application will run.
- Target
- 3000
- Default
- 3000
- Value
- 3000
Data Dir
- Target
- /app/data
- Value
- /mnt/user/appdata/dumbpad
PIN protection
- Target
- DUMBPAD_PIN
- Value
- 1234