Self-Hosted Productivity Apps: Nextcloud, BookStack, Vikunja, and Paperless-ngx
Cloud productivity tools are convenient, but they come with trade-offs: monthly costs that add up, data stored on someone else's servers, features that change or disappear at the provider's discretion, and the nagging feeling that your documents, tasks, and files are only yours as long the service lets them be.
Self-hosting productivity apps gives you full control. Your data stays on your hardware, you choose when to update, and the only monthly cost is the electricity your server already uses. The catch is setup and maintenance — but with Docker, that's gotten remarkably easy.
This guide covers four essential self-hosted productivity apps that, together, replace most of what Google Workspace or Microsoft 365 provides.
The Self-Hosted Productivity Stack
| Need | Cloud Service | Self-Hosted Alternative |
|---|---|---|
| File storage/sync | Google Drive, Dropbox, OneDrive | Nextcloud |
| Documentation/wiki | Notion, Confluence, Google Docs | BookStack |
| Task management | Todoist, Asana, Trello | Vikunja |
| Document scanning/management | Google Drive, Evernote | Paperless-ngx |
| Calendar | Google Calendar | Nextcloud (built-in) |
| Contacts | Google Contacts | Nextcloud (built-in) |
| Notes | Google Keep, Apple Notes | Nextcloud Notes or Memos |
Nextcloud: Your Personal Cloud
Nextcloud is the Swiss Army knife of self-hosted productivity. At its core, it's a file sync and share platform — like Dropbox or Google Drive. But its app ecosystem extends it into calendars, contacts, notes, office documents, video calls, and much more.
Deployment
The recommended setup uses Nextcloud with PostgreSQL and Redis for performance:
services:
nextcloud:
image: nextcloud:stable-apache
container_name: nextcloud
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./nextcloud-html:/var/www/html
- ./nextcloud-data:/var/www/html/data
- /mnt/storage/nextcloud-files:/var/www/html/data/admin/files # Optional: external storage
environment:
- POSTGRES_HOST=nextcloud-db
- POSTGRES_DB=nextcloud
- POSTGRES_USER=nextcloud
- POSTGRES_PASSWORD=secure-db-password
- REDIS_HOST=nextcloud-redis
- NEXTCLOUD_ADMIN_USER=admin
- NEXTCLOUD_ADMIN_PASSWORD=secure-admin-password
- NEXTCLOUD_TRUSTED_DOMAINS=nextcloud.home.lab
- OVERWRITEPROTOCOL=https
- OVERWRITECLIURL=https://nextcloud.home.lab
depends_on:
- nextcloud-db
- nextcloud-redis
nextcloud-db:
image: postgres:16-alpine
container_name: nextcloud-db
restart: unless-stopped
volumes:
- ./nextcloud-db:/var/lib/postgresql/data
environment:
- POSTGRES_DB=nextcloud
- POSTGRES_USER=nextcloud
- POSTGRES_PASSWORD=secure-db-password
nextcloud-redis:
image: redis:7-alpine
container_name: nextcloud-redis
restart: unless-stopped
volumes:
- ./nextcloud-redis:/data
nextcloud-cron:
image: nextcloud:stable-apache
container_name: nextcloud-cron
restart: unless-stopped
volumes:
- ./nextcloud-html:/var/www/html
- ./nextcloud-data:/var/www/html/data
entrypoint: /cron.sh
depends_on:
- nextcloud-db
- nextcloud-redis
Post-Installation Configuration
After first login, configure these settings via occ commands:
# Enter the container
docker exec -u www-data nextcloud bash
# Set the background job method to cron (already handled by nextcloud-cron container)
php occ background:cron
# Configure email notifications
php occ config:system:set mail_from_address --value="nextcloud"
php occ config:system:set mail_domain --value="home.lab"
php occ config:system:set mail_smtpmode --value="smtp"
php occ config:system:set mail_smtphost --value="smtp.home.lab"
php occ config:system:set mail_smtpport --value="587"
# Enable memory caching
php occ config:system:set memcache.local --value="\OC\Memcache\APCu"
php occ config:system:set memcache.distributed --value="\OC\Memcache\Redis"
php occ config:system:set memcache.locking --value="\OC\Memcache\Redis"
# Increase upload limits
php occ config:system:set php_upload_limit --value="16G"
Also update PHP settings for large file uploads. Create a custom PHP config:
# Create custom PHP config
docker exec nextcloud bash -c 'cat > /usr/local/etc/php/conf.d/custom.ini << EOF
upload_max_filesize = 16G
post_max_size = 16G
max_execution_time = 3600
max_input_time = 3600
memory_limit = 512M
EOF'
docker restart nextcloud
Essential Nextcloud Apps
Install these from the Nextcloud App Store (Settings > Apps):
| App | Purpose |
|---|---|
| Calendar | CalDAV calendar with sharing |
| Contacts | CardDAV contact management |
| Notes | Markdown notes synced across devices |
| Tasks | CalDAV-based task management |
| Nextcloud Office | Document editing (Collabora Online or OnlyOffice) |
| Talk | Video calls and chat |
| Deck | Kanban boards |
| News | RSS feed reader |
| Passwords | Password manager (or use Vaultwarden separately) |
Desktop and Mobile Sync
Nextcloud has sync clients for all platforms:
- Desktop: Download from nextcloud.com/install — syncs folders like Dropbox
- Android: Nextcloud app from F-Droid or Play Store
- iOS: Nextcloud app from App Store
- WebDAV: Any WebDAV client can connect to
https://nextcloud.home.lab/remote.php/dav/files/username/
Performance Tips
Nextcloud can feel sluggish without optimization:
- Use Redis: Already included in the compose file above. Without Redis, Nextcloud is noticeably slower.
- PostgreSQL over MySQL/SQLite: PostgreSQL handles concurrent access better than MySQL and is far faster than SQLite.
- Enable APCu: Local memory cache for frequently accessed data.
- SSD for database and app data: The Nextcloud database and app directory should be on an SSD. Bulk file storage can be on HDDs.
- Preview generation: Install the
previewgeneratorapp and run it on a schedule to pre-generate thumbnails instead of generating them on-demand.
# Pre-generate previews (run after large uploads)
docker exec -u www-data nextcloud php occ preview:generate-all
# Schedule preview generation
# Add to crontab or systemd timer:
# 0 2 * * * docker exec -u www-data nextcloud php occ preview:generate-all
BookStack: Documentation and Wiki
BookStack is a self-hosted wiki platform that organizes content into a hierarchy of Shelves > Books > Chapters > Pages. It's cleaner than MediaWiki, simpler than Confluence, and perfect for documenting your homelab setup, procedures, and knowledge.
Deployment
services:
bookstack:
image: lscr.io/linuxserver/bookstack:latest
container_name: bookstack
restart: unless-stopped
ports:
- "6875:80"
volumes:
- ./bookstack-config:/config
environment:
- PUID=1000
- PGID=1000
- TZ=America/New_York
- APP_URL=https://wiki.home.lab
- DB_HOST=bookstack-db
- DB_PORT=3306
- DB_USER=bookstack
- DB_PASS=secure-db-password
- DB_DATABASE=bookstackapp
depends_on:
- bookstack-db
bookstack-db:
image: mariadb:11
container_name: bookstack-db
restart: unless-stopped
volumes:
- ./bookstack-db:/var/lib/mysql
environment:
- MYSQL_ROOT_PASSWORD=secure-root-password
- MYSQL_DATABASE=bookstackapp
- MYSQL_USER=bookstack
- MYSQL_PASSWORD=secure-db-password
Default login: [email protected] / password. Change immediately.
Content Organization
BookStack's hierarchy maps naturally to homelab documentation:
Shelf: Infrastructure
├── Book: Networking
│ ├── Chapter: VLANs
│ │ ├── Page: VLAN Design
│ │ └── Page: VLAN Configuration (switch-specific)
│ ├── Chapter: DNS
│ │ ├── Page: Pi-hole Setup
│ │ └── Page: DNS Records
│ └── Chapter: VPN
│ └── Page: WireGuard Configuration
├── Book: Servers
│ ├── Chapter: Proxmox Host
│ │ ├── Page: Hardware Specs
│ │ ├── Page: Installation Notes
│ │ └── Page: GPU Passthrough Config
│ └── Chapter: NAS
│ ├── Page: ZFS Pool Layout
│ └── Page: Share Configuration
└── Book: Services
├── Chapter: Media Stack
└── Chapter: Monitoring
Shelf: Procedures
├── Book: Disaster Recovery
│ ├── Page: Backup Restoration Steps
│ └── Page: Full Rebuild Procedure
├── Book: Maintenance
│ ├── Page: Monthly Checklist
│ └── Page: Update Procedures
└── Book: Troubleshooting
├── Page: Common Issues
└── Page: Network Debugging
Why BookStack Over Alternatives
| Feature | BookStack | Wiki.js | Outline | Dokuwiki |
|---|---|---|---|---|
| Setup complexity | Very easy | Easy | Moderate | Easy |
| Editor | WYSIWYG + Markdown | Markdown + Visual | Markdown | Markup |
| Organization | Shelves/Books/Chapters | Folders | Collections/Docs | Namespaces |
| Search | Full-text | Full-text | Full-text | Full-text |
| API | REST API | GraphQL | REST API | Limited |
| Diagrams | draw.io integration | draw.io, Mermaid | Mermaid | Plugins |
| Resource usage | Low | Low | Moderate | Very low |
| Best for | Structured docs | Technical wikis | Team knowledge | Simple wikis |
BookStack wins for homelab use because its hierarchical organization matches how most people think about infrastructure documentation, and its WYSIWYG editor makes it easy to write and update without learning markup syntax.
Vikunja: Task and Project Management
Vikunja is a self-hosted task manager that replaces Todoist, Asana, or Trello. It supports lists, kanban boards, Gantt charts, and CalDAV sync — so your tasks show up in your calendar app.
Deployment
services:
vikunja:
image: vikunja/vikunja:latest
container_name: vikunja
restart: unless-stopped
ports:
- "3456:3456"
volumes:
- ./vikunja-files:/app/vikunja/files
- ./vikunja-db:/db
environment:
VIKUNJA_SERVICE_PUBLICURL: https://tasks.home.lab
VIKUNJA_DATABASE_TYPE: sqlite
# For PostgreSQL instead:
# VIKUNJA_DATABASE_TYPE: postgres
# VIKUNJA_DATABASE_HOST: vikunja-db
# VIKUNJA_DATABASE_DATABASE: vikunja
# VIKUNJA_DATABASE_USER: vikunja
# VIKUNJA_DATABASE_PASSWORD: secure-password
VIKUNJA_SERVICE_ENABLEREGISTRATION: "false"
VIKUNJA_MAILER_ENABLED: "false"
Features Worth Using
Kanban boards: Drag-and-drop task management. Create boards for different areas:
- Homelab Projects (to-do, in progress, done)
- Shopping List (to buy, ordered, delivered)
- Learning (to learn, studying, completed)
CalDAV integration: Sync tasks with Nextcloud, Thunderbird, or any CalDAV client:
- CalDAV URL:
https://tasks.home.lab/dav/principals/username/ - Tasks appear as calendar items with due dates
Labels and filters: Tag tasks across projects and create saved filters:
urgent+homelab= things that need fixing nowsomeday+learning= things to explore when you have time
Repeating tasks: Set up recurring tasks for homelab maintenance:
- Weekly: Check backup status
- Monthly: Review firewall rules, update containers
- Quarterly: Test disaster recovery
Task Organization for Homelabbers
Project: Homelab Maintenance
├── List: Weekly Tasks
│ ├── Verify backup completion
│ ├── Check monitoring dashboards
│ └── Review system updates
├── List: Monthly Tasks
│ ├── Test backup restoration
│ ├── Review container image updates
│ ├── Check certificate expiration
│ └── Review firewall rules
└── List: Quarterly Tasks
├── Full disaster recovery test
├── Review access permissions
└── Clean up unused containers/images
Project: Homelab Upgrades
├── List: Planning
├── List: In Progress
└── List: Completed
Paperless-ngx: Document Management
Paperless-ngx turns your homelab into a paperless office. Scan documents (receipts, bills, letters, manuals), and Paperless automatically OCRs them, extracts metadata, and makes everything searchable. It's the self-hosted equivalent of a filing cabinet that you can search instantly.
Deployment
services:
paperless:
image: ghcr.io/paperless-ngx/paperless-ngx:latest
container_name: paperless
restart: unless-stopped
ports:
- "8000:8000"
volumes:
- ./paperless-data:/usr/src/paperless/data
- ./paperless-media:/usr/src/paperless/media
- ./paperless-export:/usr/src/paperless/export
- ./paperless-consume:/usr/src/paperless/consume # Drop files here
environment:
PAPERLESS_REDIS: redis://paperless-redis:6379
PAPERLESS_DBHOST: paperless-db
PAPERLESS_DBNAME: paperless
PAPERLESS_DBUSER: paperless
PAPERLESS_DBPASS: secure-db-password
PAPERLESS_SECRET_KEY: change-this-to-a-long-random-string
PAPERLESS_URL: https://docs.home.lab
PAPERLESS_ADMIN_USER: admin
PAPERLESS_ADMIN_PASSWORD: secure-admin-password
PAPERLESS_OCR_LANGUAGE: eng
PAPERLESS_CONSUMER_RECURSIVE: "true"
PAPERLESS_CONSUMER_SUBDIRS_AS_TAGS: "true"
PAPERLESS_FILENAME_FORMAT: "{created_year}/{correspondent}/{title}"
USERMAP_UID: 1000
USERMAP_GID: 1000
depends_on:
- paperless-db
- paperless-redis
paperless-db:
image: postgres:16-alpine
container_name: paperless-db
restart: unless-stopped
volumes:
- ./paperless-db:/var/lib/postgresql/data
environment:
POSTGRES_DB: paperless
POSTGRES_USER: paperless
POSTGRES_PASSWORD: secure-db-password
paperless-redis:
image: redis:7-alpine
container_name: paperless-redis
restart: unless-stopped
How the Workflow Works
- Consume: Drop a PDF, image, or scan into the
consumedirectory (or use the web UI upload, email, or mobile app) - OCR: Paperless runs Tesseract OCR on the document, making it full-text searchable
- Classify: Automatic matching rules assign correspondents (who sent it), document types (invoice, receipt, letter), and tags
- Store: The original file is stored with a structured filename in the media directory
- Search: Find any document instantly by content, date, correspondent, or tags
Setting Up Auto-Classification
Paperless can automatically classify documents. Set up matching rules:
Correspondent: "Electric Company"
Match: "Electric Utility" OR "power bill"
Matching algorithm: Any word
Document Type: "Invoice"
Match: "invoice" OR "amount due" OR "payment due"
Matching algorithm: Any word
Tag: "Tax Deductible"
Match: "business expense" OR "home office"
Matching algorithm: Any word
Scanning Workflow
Phone scanning: Use the Paperless-ngx mobile app or any scanning app that can upload to a folder:
- Android: Paperless mobile app, or use "Scan to folder" with Nextcloud
- iOS: Paperless mobile app, or use the built-in document scanner and upload
Network scanner: Configure your scanner to save to the Paperless consume directory via SMB/NFS:
# Create an SMB share for the consume directory
# In /etc/samba/smb.conf:
[paperless]
path = /path/to/paperless-consume
writeable = yes
valid users = scanner
Email consumption: Paperless can automatically ingest email attachments:
environment:
PAPERLESS_EMAIL_TASK_CRON: "*/10 * * * *" # Check every 10 minutes
# Configure in the web UI under Admin > Mail Accounts
Document Organization
A practical tagging scheme:
Correspondents:
- Bank (statements, notices)
- Insurance (policies, claims)
- Utilities (power, water, internet)
- Government (tax forms, licenses)
- Medical (bills, records)
Document Types:
- Invoice
- Receipt
- Statement
- Contract
- Manual
- Letter
Tags:
- Tax (year) — e.g., "Tax 2025", "Tax 2026"
- Important
- Action Required
- Warranty
- Homelab
Connecting Everything Together
Single Sign-On with Authentik
If you're running all four apps, a single sign-on solution prevents having to manage separate accounts:
authentik:
image: ghcr.io/goauthentik/server:latest
container_name: authentik
restart: unless-stopped
command: server
ports:
- "9000:9000"
volumes:
- ./authentik-media:/media
- ./authentik-templates:/templates
environment:
AUTHENTIK_SECRET_KEY: generate-a-long-random-string
AUTHENTIK_REDIS__HOST: authentik-redis
AUTHENTIK_POSTGRESQL__HOST: authentik-db
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: secure-password
AUTHENTIK_POSTGRESQL__NAME: authentik
Nextcloud, BookStack, and Vikunja all support OIDC/OAuth2 authentication. Configure each app to use Authentik as the identity provider, and you get a single login for everything.
Reverse Proxy Configuration
Behind a reverse proxy (Caddy example):
nextcloud.home.lab {
reverse_proxy nextcloud:80
request_body {
max_size 16GB
}
}
wiki.home.lab {
reverse_proxy bookstack:80
}
tasks.home.lab {
reverse_proxy vikunja:3456
}
docs.home.lab {
reverse_proxy paperless:8000
}
Backup Strategy
These apps contain important personal data. Back them up:
#!/bin/bash
# backup-productivity.sh
BACKUP_DIR="/mnt/backup/productivity"
DATE=$(date +%Y-%m-%d)
mkdir -p "$BACKUP_DIR"
# Database dumps
docker exec nextcloud-db pg_dumpall -U nextcloud > "$BACKUP_DIR/nextcloud-$DATE.sql"
docker exec bookstack-db mysqldump -u root --password=secure-root-password bookstackapp > "$BACKUP_DIR/bookstack-$DATE.sql"
docker exec paperless-db pg_dumpall -U paperless > "$BACKUP_DIR/paperless-$DATE.sql"
# Application data
tar -czf "$BACKUP_DIR/nextcloud-data-$DATE.tar.gz" ./nextcloud-data
tar -czf "$BACKUP_DIR/bookstack-config-$DATE.tar.gz" ./bookstack-config
tar -czf "$BACKUP_DIR/paperless-media-$DATE.tar.gz" ./paperless-media
tar -czf "$BACKUP_DIR/vikunja-$DATE.tar.gz" ./vikunja-files ./vikunja-db
# Rotate (keep 7 days)
find "$BACKUP_DIR" -name "*.sql" -mtime +7 -delete
find "$BACKUP_DIR" -name "*.tar.gz" -mtime +7 -delete
Resource Requirements
| App | RAM (minimum) | RAM (recommended) | CPU | Storage |
|---|---|---|---|---|
| Nextcloud + DB + Redis | 1GB | 2-4GB | 2 cores | 10GB + files |
| BookStack + DB | 512MB | 1GB | 1 core | 2GB |
| Vikunja (SQLite) | 128MB | 256MB | 0.5 cores | 1GB |
| Paperless-ngx + DB + Redis | 1GB | 2GB | 2 cores | 5GB + documents |
| Total | ~3GB | ~6-8GB | 4-6 cores | 20GB + data |
All four apps run comfortably on a single server with 8GB of RAM. They're not resource-intensive — the main storage consideration is how much file/document data you accumulate.
Final Thoughts
Self-hosted productivity apps hit a sweet spot between cloud convenience and data ownership. Nextcloud replaces Google Drive and calendar, BookStack replaces Notion or Confluence for documentation, Vikunja replaces Todoist for task management, and Paperless-ngx turns your paper pile into a searchable archive.
The setup time for all four is about an afternoon. The maintenance is minimal — update containers monthly, verify backups weekly, and they largely run themselves. The payoff is knowing that your files, documents, tasks, and notes are yours, on your hardware, under your control.
Start with whichever one solves your most pressing need. For most people, that's Nextcloud (everyone needs file sync) or Paperless-ngx (everyone has a pile of paper they should deal with). Add the others as you see the value.