ทำไมต้อง Self-Hosted Cloud Storage
ผมเลิกใช้ Google Drive สำหรับข้อมูลสำคัญตั้งแต่ปี 2018 เหตุผลหลักคือ data sovereignty ข้อมูลลูกค้าเอกสารสัญญา financial records ทั้งหมดอยู่บน server ของ Google ที่เราควบคุมไม่ได้ Google อาจเปลี่ยน terms of service, ขึ้นราคา, หรือแม้แต่ปิด account ได้ทุกเมื่อ
Nextcloud เป็น open-source self-hosted cloud platform ที่ทดแทน Google Workspace ได้เกือบทั้งหมดไม่ใช่แค่ file sync แต่ยังมี Calendar, Contacts, Email integration, Office documents (Collabora/OnlyOffice), Video conferencing (Nextcloud Talk), Kanban boards, Forms, Bookmarks และ apps อีกหลายร้อยตัว
Nextcloud vs ownCloud vs Seafile
Nextcloud เป็น fork ของ ownCloud ที่ community ใหญ่กว่ามี apps ecosystem ที่สมบูรณ์ที่สุด ownCloud focus ที่ enterprise file sync เป็นหลัก UI สวยแต่ community เล็กกว่า Seafile เน้น performance สำหรับ large file sync มี delta sync ที่ดีมากแต่ features นอก file sync มีน้อยผมเลือก Nextcloud เพราะมันเป็น complete platform ที่ทดแทน Google Workspace ได้จริง
Docker Compose Stack
# docker-compose.yml — Nextcloud Production Stack
services:
nextcloud-db:
image: mariadb:11.3
command: --transaction-isolation=READ-COMMITTED --log-bin=binlog --binlog-format=ROW
volumes:
- nextcloud-db:/var/lib/mysql
environment:
MYSQL_ROOT_PASSWORD: RootPass_Secure_2026!
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_PASSWORD: NCPass_Secure_2026!
restart: unless-stopped
nextcloud-redis:
image: redis:7-alpine
command: redis-server --requirepass RedisPass_2026!
volumes:
- nextcloud-redis:/data
restart: unless-stopped
nextcloud-app:
image: nextcloud:29-apache
volumes:
- nextcloud-html:/var/www/html
- nextcloud-data:/var/www/html/data
- nextcloud-config:/var/www/html/config
environment:
MYSQL_HOST: nextcloud-db
MYSQL_DATABASE: nextcloud
MYSQL_USER: nextcloud
MYSQL_PASSWORD: NCPass_Secure_2026!
REDIS_HOST: nextcloud-redis
REDIS_HOST_PASSWORD: RedisPass_2026!
NEXTCLOUD_ADMIN_USER: admin
NEXTCLOUD_ADMIN_PASSWORD: AdminPass_Secure_2026!
NEXTCLOUD_TRUSTED_DOMAINS: cloud.example.com
OVERWRITEPROTOCOL: https
OVERWRITECLIURL: https://cloud.example.com
PHP_MEMORY_LIMIT: 1G
PHP_UPLOAD_LIMIT: 16G
depends_on:
- nextcloud-db
- nextcloud-redis
restart: unless-stopped
nextcloud-cron:
image: nextcloud:29-apache
volumes:
- nextcloud-html:/var/www/html
- nextcloud-data:/var/www/html/data
- nextcloud-config:/var/www/html/config
entrypoint: /cron.sh
depends_on:
- nextcloud-db
- nextcloud-redis
restart: unless-stopped
volumes:
nextcloud-db:
nextcloud-redis:
nextcloud-html:
nextcloud-data:
driver: local
driver_opts:
type: none
o: bind
device: /mnt/data/nextcloud
nextcloud-config:
เริ่มต้นใช้งาน
# สร้าง data directory
mkdir -p /mnt/data/nextcloud
chown -R 33:33 /mnt/data/nextcloud # www-data user
# เริ่ม stack
docker compose up -d
# ดู logs
docker compose logs -f nextcloud-app
# รอจน installation เสร็จ (ประมาณ 1-2 นาที)
# เข้า http://server-ip:80 เพื่อ setup
Nginx Configuration
# /etc/nginx/sites-available/nextcloud.conf
upstream nextcloud_backend {
server 127.0.0.1:8080;
keepalive 64;
}
server {
listen 80;
server_name cloud.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name cloud.example.com;
ssl_certificate /etc/letsencrypt/live/cloud.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/cloud.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
client_max_body_size 16G;
client_body_timeout 3600s;
fastcgi_buffers 64 4K;
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Content-Type-Options nosniff always;
add_header X-Frame-Options SAMEORIGIN always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy no-referrer always;
location / {
proxy_pass http://nextcloud_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_max_temp_file_size 16384m;
proxy_request_buffering off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}
location /.well-known/carddav {
return 301 $scheme://$host/remote.php/dav;
}
location /.well-known/caldav {
return 301 $scheme://$host/remote.php/dav;
}
}
Let's Encrypt SSL
# ติดตั้ง Certbot
apt install certbot python3-certbot-nginx
# ขอ certificate
certbot --nginx -d cloud.example.com
# Auto-renew
systemctl enable certbot.timer
Nextcloud config.php Tuning
# เข้าไปแก้ config ผ่าน Docker
docker compose exec nextcloud-app bash
# แก้ /var/www/html/config/config.php
# เพิ่มค่าต่อไปนี้:
'memcache.local' => '\\OC\\Memcache\\APCu',
'memcache.distributed' => '\\OC\\Memcache\\Redis',
'memcache.locking' => '\\OC\\Memcache\\Redis',
'redis' => [
'host' => 'nextcloud-redis',
'port' => 6379,
'password' => 'RedisPass_2026!',
],
'default_phone_region' => 'TH',
'default_locale' => 'th_TH',
'default_language' => 'th',
'maintenance_window_start' => 1,
'filelocking.enabled' => true,
'enable_previews' => true,
'preview_max_x' => 2048,
'preview_max_y' => 2048,
'jpeg_quality' => 60,
'trashbin_retention_obligation' => 'auto, 30',
MariaDB Tuning สำหรับ Nextcloud
# เพิ่มใน docker-compose.yml สำหรับ MariaDB
# หรือ mount custom config file
# /etc/mysql/conf.d/nextcloud.cnf
[mysqld]
innodb_buffer_pool_size = 1G
innodb_io_capacity = 4000
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
innodb_file_per_table = 1
read_rnd_buffer_size = 512K
sort_buffer_size = 512K
join_buffer_size = 256K
Background Jobs
# ตรวจสอบว่า cron ทำงาน
docker compose exec nextcloud-app php occ background:cron
# รัน maintenance tasks
docker compose exec nextcloud-app php occ maintenance:repair
docker compose exec nextcloud-app php occ db:add-missing-indices
docker compose exec nextcloud-app php occ db:convert-filecache-bigint
# Scan files ใหม่ (ถ้า upload ผ่าน filesystem โดยตรง)
docker compose exec nextcloud-app php occ files:scan --all
Productivity Apps
# ติดตั้ง apps ผ่าน occ CLI
docker compose exec nextcloud-app php occ app:install calendar
docker compose exec nextcloud-app php occ app:install contacts
docker compose exec nextcloud-app php occ app:install tasks
docker compose exec nextcloud-app php occ app:install notes
docker compose exec nextcloud-app php occ app:install deck # Kanban boards
docker compose exec nextcloud-app php occ app:install forms # Google Forms alternative
docker compose exec nextcloud-app php occ app:install bookmarks
Collabora Online — Office ใน Browser
# เพิ่มใน docker-compose.yml
collabora:
image: collabora/code:24.04
environment:
aliasgroup1: https://cloud.example.com:443
username: admin
password: CollaboraPass_2026!
extra_params: --o:ssl.enable=false --o:ssl.termination=true
ports:
- "9980:9980"
restart: unless-stopped
# ตั้งค่า Nginx proxy สำหรับ Collabora
# server block เพิ่ม:
location /browser {
proxy_pass http://127.0.0.1:9980;
proxy_set_header Host $host;
}
location /hosting/discovery {
proxy_pass http://127.0.0.1:9980;
proxy_set_header Host $host;
}
location /cool {
proxy_pass http://127.0.0.1:9980;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
# ติดตั้ง Collabora app ใน Nextcloud
docker compose exec nextcloud-app php occ app:install richdocuments
# ตั้งค่า Collabora server URL ใน Admin Settings
Backup Script
#!/bin/bash
# /usr/local/bin/nextcloud-backup.sh
BACKUP_DIR="/backup/nextcloud"
DATE=$(date +%Y%m%d)
NC_DIR="/mnt/data/nextcloud"
mkdir -p "/"
# 1. เปิด Maintenance Mode
docker compose exec -T nextcloud-app php occ maintenance:mode --on
# 2. Backup Database
docker compose exec -T nextcloud-db mysqldump \
-u nextcloud -p'NCPass_Secure_2026!' \
nextcloud | gzip > "//database.sql.gz"
# 3. Backup Config
docker compose exec -T nextcloud-app \
tar czf - /var/www/html/config > "//config.tar.gz"
# 4. Backup Data (incremental with rsync)
rsync -a --delete "/" "//data/"
# 5. ปิด Maintenance Mode
docker compose exec -T nextcloud-app php occ maintenance:mode --off
# 6. ลบ backup เก่ากว่า 30 วัน
find "" -maxdepth 1 -type d -mtime +30 -exec rm -rf {} +
echo "Backup completed: /"
# Crontab: 0 3 * * * /usr/local/bin/nextcloud-backup.sh
Restore จาก Backup
# 1. หยุด Nextcloud
docker compose down
# 2. Restore database
zcat /backup/nextcloud/20260228/database.sql.gz | \
docker compose exec -T nextcloud-db mysql -u nextcloud -p'NCPass_Secure_2026!' nextcloud
# 3. Restore config
docker compose exec -T nextcloud-app \
tar xzf - -C / < /backup/nextcloud/20260228/config.tar.gz
# 4. Restore data
rsync -a /backup/nextcloud/20260228/data/ /mnt/data/nextcloud/
# 5. Fix permissions
chown -R 33:33 /mnt/data/nextcloud
# 6. เริ่ม Nextcloud
docker compose up -d
docker compose exec nextcloud-app php occ maintenance:repair
docker compose exec nextcloud-app php occ files:scan --all
External Storage และ S3
Nextcloud รองรับ external storage หลายแบบทำให้ไม่ต้องเก็บทุกอย่างบน local disk
เชื่อมต่อ S3 Compatible Storage
# ติดตั้ง External Storage app
docker compose exec nextcloud-app php occ app:install files_external
# ตั้งค่าผ่าน config.php หรือ Admin UI
# สำหรับ MinIO / S3 compatible storage:
'objectstore' => [
'class' => '\\OC\\Files\\ObjectStore\\S3',
'arguments' => [
'bucket' => 'nextcloud-data',
'hostname' => 's3.example.com',
'port' => 443,
'use_ssl' => true,
'region' => 'ap-southeast-1',
'key' => 'YOUR_ACCESS_KEY',
'secret' => 'YOUR_SECRET_KEY',
'use_path_style' => true,
],
],
สำหรับการ sync ข้อมูลไปยัง cloud storage หลายที่ดูบทความ Rclone Cloud Sync ของผม
Mount CIFS/SMB Share
# mount Windows share หรือ NAS ใน Nextcloud
# ผ่าน Admin > External Storage
# Type: SMB/CIFS
# Configuration: //nas-server/shared
# Authentication: username/password
# Available for: specific groups
# หรือ mount NFS จาก Linux NAS
# เพิ่มใน docker-compose.yml volumes:
volumes:
- type: volume
source: nfs-archive
target: /mnt/archive
volume:
nocopy: true
# Docker volume definition
volumes:
nfs-archive:
driver: local
driver_opts:
type: nfs
o: addr=10.10.10.50, rw, nfsvers=4
device: ":/export/archive"
Nextcloud ช้าเมื่อมีไฟล์เยอะทำยังไง?
ปัญหานี้เจอบ่อยเมื่อมีไฟล์หลายแสนไฟล์ทางแก้คือตั้ง Redis สำหรับ file locking และ distributed cache, เพิ่ม PHP memory limit เป็น 1GB+, ใช้ MySQL/MariaDB tuning ที่เหมาะสม, enable preview generation ล่วงหน้าด้วย app "Preview Generator" และรัน occ files:scan สม่ำเสมอสำหรับ large deployments ผมแนะนำใช้ S3 object store แทน local filesystem
Nextcloud Hub กับ Google Workspace ต่างกันยังไง?
Google Workspace เป็น managed service ที่ทำงานได้ทันทีไม่ต้องดูแล server แต่ข้อมูลอยู่บน Google cloud ราคาเริ่มต้น $7/user/month Nextcloud Hub ฟรี (open-source) ข้อมูลอยู่บน server ของเรา 100% customizable ได้เต็มที่แต่ต้องดูแล server เองสำหรับองค์กรที่มี IT team ผมแนะนำ Nextcloud เพราะ data sovereignty และไม่มีค่า license ต่อ user
Upload ไฟล์ใหญ่ไม่ได้ทำยังไง?
ต้องตั้งค่าหลายจุด PHP upload_max_filesize และ post_max_size ตั้งให้เท่ากัน (เช่น 16G) Nginx client_max_body_size ตั้งให้เท่ากัน proxy_read_timeout และ proxy_send_timeout ตั้งให้สูงพอ (3600s สำหรับไฟล์ใหญ่) ใน docker-compose.yml ตั้ง PHP_UPLOAD_LIMIT=16G และใช้ Nextcloud desktop client สำหรับ upload ไฟล์ใหญ่เพราะรองรับ chunked upload ที่ resume ได้
Nextcloud Talk ใช้แทน Zoom ได้ไหม?
ได้ครับสำหรับทีมเล็ก (5-10 คน) Nextcloud Talk รองรับ video/audio call, screen sharing, chat แต่ถ้าต้องการ meeting กับคนเยอะ (50+ คน) ต้องติดตั้ง TURN server (coturn) และ High-Performance Backend (HPB) ซึ่งซับซ้อนกว่าสำหรับ large meetings ผมยังแนะนำ Jitsi Meet ที่เป็น open-source เหมือนกันแต่ออกแบบมาสำหรับ video conferencing โดยเฉพาะ
สรุป
Nextcloud เป็น self-hosted cloud platform ที่สมบูรณ์ที่สุดในตลาด open-source ทดแทน Google Drive, Calendar, Contacts, Office ได้ทั้งหมดข้อมูลอยู่บน server ของเราเอง 100% ไม่มีค่า license ต่อ user
สิ่งสำคัญคือ performance tuning ตั้ง Redis cache, tune MariaDB, ใช้ Nginx reverse proxy พร้อม SSL และ backup ทุกวันผมรัน Nextcloud สำหรับทีม 50+ คนมา 6 ปีไม่มีปัญหา uptime 99.9%+ ด้วย Docker Compose deployment ที่แสดงในบทความนี้ครับ
