Služby na NAS
Co se dozvíte v článku
Když mluvíme o NAS, většinou máme na mysli „krabici s disky, která umí sdílet soubory“. Ale co všechno to konkrétně znamená? V mém případě jsem měl několik základních požadavků na funkce, které bych od NAS řešení očekával
- SAMBA – sdílení souborů pro Windows i Linux v rámci domácí sítě
- Web UI – rozhraní pro přístup k souborům odkudkoliv přes prohlížeč
- Mobilní aplikace – přístup ze sítě i internetu přes telefon
- Nginx proxy – jako reverse proxy pro přístup ke kontejnerizovaným aplikacím a TLS terminace
- VPN (WireGuard) – bezpečné připojení k domácí síti odkudkoliv
Každou z těchto služeb si rozebereme. Nejen z hlediska funkčnosti, ale i udržitelnosti tedy toho, aby bylo vše přehledné, spravovatelné a ideálně dlouhodobě stabilní.
Samba a sdílení souborů
Začněme hned tou nejčastější a pro mě nejdůležitější funkcí NAS, sdílení souborů přes protokol Samba.
Instalace Samby
sudo apt install samba
Základní konfigurace /etc/samba/smb.conf
[global] # Informace o serveru workgroup = WORKGROUP server string = NAS Server netbios name = NAS # Režim a zabezpečení server role = standalone server security = user map to guest = bad user # Síťová rozhraní bind interfaces only = yes interfaces = lo enp1s0 # Logování log file = /var/log/samba/log.%m max log size = 10000 log level = 1 # Práva při vytváření souborů create mask = 0664 directory mask = 0775 force create mode = 0644 force directory mode = 0755 # Vypnutí podpory tisku load printers = no printing = bsd printcap name = /dev/null disable spoolss = yes show add printer wizard = no
Doporučuji věnovat zvláštní pozornost sekcím Síťová rozhraní, Práva při vytváření souborů a global v konfiguraci. Nastavení výše je vhodné pro většinu domácích uživatelů, ale určitě se vyplatí si projít dokumentaci Samby pro vaši verzi a upravit si parametry podle konkrétních potřeb.
Poznámka: V době psaní článku používám Sambu ve verzi 4.19.5, kde jsou starší protokoly (např. SMBv1) ve výchozím stavu deaktivovány. Což je dobře, jen to zmiňuji, abyste si na staré protokoly dali pozor.
Konfigurace jednotlivých sdílených složek (tzv. shares)
Níže jsou tři konkrétní příklady, které používám:
- 1. Uživatelské adresáře (domovské složky)
- 2. Sdílení multimédií (video, hudba, fotky)
- 3. Záloha dat
# Domovské složky (přístup chráněn heslem) [homes] comment = Home directories path = /nas/homes/%S browseable = yes writable = yes guest ok = no valid users = @sambausers read only = no create mask = 0660 directory mask = 0770 # Veřejné sdílení multimédií [Multimedia] comment = Media Files path = /nas/multimedia browseable = yes writable = yes guest ok = yes read only = no force user = nobody force group = nogroup # Zálohovací sdílení [Backup] comment = Backups path = /nas/data/backup browseable = no writable = yes guest ok = no read only = no force user = nobody force group = nogroup
Díky těmto třem základním sdíleným složkám mám pokrytou většinu domácích potřeb osobní data, multimédia i zálohy. Každá z nich má jiné parametry podle toho, jaký způsob přístupu a zabezpečení očekávám.
Autodiscovery
Není nutné používat automatické objevování, ale v domácí síti vám může značně zvýšit komfort hlavně pro méně zkušené uživatele (babička se chce podívat na fotky z dovolené). Jinak je to samozřejmě něco za něco. Nedá mi nezmínit, že implementace autodiscovery nejsou obecně považovány za bezpečné. Do podnikové sítě bych to asi nedoporučil, ale do domácí v zásadě proč ne.
- Linux, instalací
avahi-serverzískáte service discovery. Můžete takto do sítě oznamovat služby NAS. - Windows 10+, instalací aplikace wsdd získáte service discovery pro Windows.
Konfiguraci k oběma najdete v repozitáři k tomuto článku.
Přístup z internetu
Dnes už nestačí mít NAS dostupný jen přes sdílení v lokální síti. Potřebujeme pohodlný přístup k datům odkudkoli a hlavně kdykoliv, a to jak z prohlížeče, tak třeba z mobilního telefonu. Tady přichází na řadu webové rozhraní a mobilní aplikace.
Možností, jak to celé postavit, je víc a právě tady často narazíte na problémy s oprávněními k souborům. Webová nebo mobilní aplikace totiž musí mít přístup k datům, ale zároveň na NAS existují privátní adresáře uživatelů, do kterých nechceme pustit nikoho jiného, ani skupiny či ostatní uživatele.
Ve svém případě mám k dispozici od poskytovatele dynamickou veřejnou IP adresu. Budu tedy konfigurovat vše tak, abych ji využil. O veřejnou adresu a propagaci DynDNS se stará router a není to obsahem tohoto článku. Jen zmíním, že moje soukromá doména pro NAS směřuje jako CNAME na záznam DynDNS pro moji veřejnou adresu.
Jak nasazovat a spravovat aplikace?
Zvolil jsem cestu přes Docker a kontejnerizaci. Pokud s Dockerem nemáte zkušenosti, doporučuji nejdřív projít oficiální návod k instalaci Docker Engine.
Všechno jsem postavil na jednoduchém principu: každá aplikace má vlastní adresář s docker-compose.yml a o její spuštění se stará univerzální šablona systemd.
Hlavní výhodou tohoto řešení je, že:
- můžete nasazovat i složitější aplikace složené z více kontejnerů (např. ownCloud + MariaDB + Redis),
- vše se spouští konzistentně, přehledně a stejně,
- můžete snadno řešit závislosti, restartování a healthchecky,
- není třeba řešit složitější orchestrace typu Kubernetes, k3s nebo Nomad.
Šablona systemd pro správu kontejnerů ( /etc/systemd/system/dc@.service)
[Unit] Description=Docker services started by docker compose After=network.target auditd.service docker.service Requires=docker.service [Service] Restart=always StandardOutput=null ExecStartPre=/usr/bin/docker compose --project-directory /containers/%i/ -f /containers/%i/docker-compose.yml down -v ExecStart=/usr/bin/docker compose --project-directory /containers/%i/ -f /containers/%i/docker-compose.yml up ExecStop=/usr/bin/docker compose --project-directory /containers/%i/ -f /containers/%i/docker-compose.yml down Restart=on-failure [Install] WantedBy=multi-user.target
Web UI a mobilní aplikace
Nakonec jsem se rozhodl pro nasazení ownCloudu. Samozřejmě, alternativou je i dnes známější Nextcloud, ale ten mi přišel pro můj účel zbytečně „nabitý“, chcete-li veliký. Obsahuje sice spoustu funkcí, ale já jsem potřeboval jen jednoduché a funkční řešení pro přístup k datům a jejich sdílení. ownCloud v základní verzi umí přesně to, co potřebuji, bez zbytečné složitosti, bez zbytečných modulů.
Nasazení ownCloudu
Nejprve obnovíme konfiguraci systemd, kvůli šabloně kterou jsme vytvořili:
systemctl daemon-reload
Poté připravíme strukturu adresářů:
# Konfigurační adresář mkdir -p /containers/owncloud # Perzistentní data mkdir -p /var/lib/containers-data/owncloud
Do /containers/owncloud/ uložíme docker-compose.yml, který definuje služby ownCloud, MariaDB a Redis.
Ukázka docker-compose.yml:
volumes:
files:
driver: local
driver_opts:
o: bind
type: none
device: /var/lib/containers-data/owncloud/server
db:
driver: local
driver_opts:
o: bind
type: none
device: /var/lib/containers-data/owncloud/mariadb
dbbackup:
driver: local
driver_opts:
o: bind
type: none
device: /var/lib/containers-data/owncloud/dbbackup
redis:
driver: local
driver_opts:
o: bind
type: none
device: /var/lib/containers-data/owncloud/redis
services:
owncloud:
image: owncloud/server:${OWNCLOUD_VERSION}
container_name: owncloud_server
restart: always
ports:
- ${HTTP_PORT}:8080
depends_on:
- mariadb
- redis
environment:
- OWNCLOUD_DOMAIN=${OWNCLOUD_DOMAIN}
- OWNCLOUD_DB_TYPE=mysql
- OWNCLOUD_DB_NAME=owncloud
- OWNCLOUD_DB_USERNAME=${DB_USERNAME}
- OWNCLOUD_DB_PASSWORD=${DB_PASSWORD}
- OWNCLOUD_DB_HOST=mariadb
- OWNCLOUD_ADMIN_USERNAME=${ADMIN_USERNAME}
- OWNCLOUD_ADMIN_PASSWORD=${ADMIN_PASSWORD}
- OWNCLOUD_MYSQL_UTF8MB4=true
- OWNCLOUD_REDIS_ENABLED=true
- OWNCLOUD_REDIS_HOST=redis
healthcheck:
test: ["CMD", "/usr/bin/healthcheck"]
interval: 30s
timeout: 10s
retries: 5
volumes:
- files:/mnt/data
mariadb:
image: mariadb:10.5
container_name: owncloud_mariadb
restart: always
environment:
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
- MYSQL_USER=${DB_USERNAME}
- MYSQL_PASSWORD=${DB_PASSWORD}
- MYSQL_DATABASE=owncloud
command: ["--max-allowed-packet=128M", "--innodb-log-file-size=64M"]
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-u", "root", "--password=owncloud"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- db:/var/lib/mysql
- dbbackup:/backup
redis:
image: redis:6
container_name: owncloud_redis
restart: always
command: ["--databases", "1"]
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
volumes:
- redis:/data
Citlivé údaje ukládáme do .env
OWNCLOUD_VERSION=10.15.2 OWNCLOUD_DOMAIN=moje.domena.tld ADMIN_USERNAME=admin ADMIN_PASSWORD=xxxxxxyyyyxxxx HTTP_PORT=8080 DB_USERNAME=owncloud DB_PASSWORD=xxxxxxxxxxxxx DB_ROOT_PASSWORD=owncloud
Spuštění služby
Díky šabloně systemd stačí už jen aktivovat a nastartovat službu:
# Aktivace služby při startu systemctl enable dc@owncloud.service # První spuštění systemctl start dc@owncloud.service
Tím máme hotovo. Takto můžete velmi snadno přidávat i další aplikace, stačí vytvořit nový adresář, připravit docker-compose.yml a spustit příslušnou službu v systemd. Nasazení nové aplikace je pak otázka minut.
Co přístupová práva?
To byla klíčová otázka. Jak zajistit přístup ke konkrétním adresářům bez toho, aby aplikace ownCloud viděla do adresářů všech ostatních? Řešení je překvapivě jednoduché a je možné jej stejně použít v ownCloudu i Nextcloudu. Využijeme funkci External Storage. Ta umožňuje připojit adresáře přes různé síťové protokoly do prostoru konkrétního uživatele.
Tímto způsobem uživatel vidí jen to, co má vidět, a zároveň získává pohodlný přístup k datům odkudkoliv – z webu, mobilní aplikace nebo desktopového klienta. Práva zůstávají zachována podle nastavení v systému a není potřeba je nijak složitě obcházet. Přístup k datům je navíc centralizovaný přes Sambu a tedy případné auditování práce nad soubory je na jednom místě v logu.
Co je potřeba udělat
- Povolit podporu External Storage v administraci ownCloudu/Nextcloudu,
- přidělit uživatelům oprávnění pro připojení vlastních externích adresářů,
- u uživatele nakonfigurovat přístup ke konkrétní sdílené složce (to si udělá každý uživatel sám).
Jako administrátor povolím „External Storage“ včetně sdílení. Pokud funkci sdílení nepotřebujete, tak ji nezaškrtávejte. Já ji ale rád používám.
Jako uživatel si následně připojím svůj Samba share a přístup k souborům je poté vždy přes Sambu.
Tento přístup má hned několik výhod:
- ownCloud vůbec nemusí mít přímý přístup k datům – nesahá tedy přímo do adresářů na disku. Všechno probíhá přes protokol Samby.
- Audit přístupu funguje jednotně – mobilní aplikace i webové rozhraní a přístup z lokální sítě přistupují k souborům přes Sambu, veškeré přístupy se logují v rámci Samby.
- Možnost sdílet adresáře napříč uživateli – jako správce můžete například připojit veřejný adresář Multimedia automaticky všem uživatelům.
Zálohování MariaDB
Databázi je potřeba samozřejmě zálohovat vhodným způsobem. Pro kontejnerizované aplikace je možné volat příkazy přímo přes řádkové rozhraní Dockeru. Zálohování je samo o sobě široká téma, ale nechci to úplně přeskočit. Na zálohování používam Restic.
Příklad toho jak vytvořit zálohu MariaDB:
# Načteme heslo z containeru MYSQL_ROOT_PASSWORD="$(docker exec owncloud-mariadb-1 printenv MYSQL_ROOT_PASSWORD)" # vytvoříme binární zálohu docker exec owncloud-mariadb-1 mariadb-backup --backup --target-dir=/backup/ -u root --password=$MYSQL_ROOT_PASSWORD # nebo sql dump per db DATABASES=$(docker exec owncloud-mariadb-1 mariadb -u root --password=$MYSQL_ROOT_PASSWORD -N -e "SHOW DATABASES") for database in $DATABASES ; do docker exec owncloud-mariadb-1 mariadb-dump -u root --password=$MYSQL_ROOT_PASSWORD --routines --triggers --single-transaction "$database" -r /backup/$database.dump done
Tyto snippety nam zálohují databáze do předpřipraveného adresáře /backup. Tento adresář směřuje v hlavním systému do /var/lib/containers-data/owncloud/dbbackup. V mém případě celé umístění /var/lib/containers-data zálohuju pomoci Restic. Berte to spíš jako inspiraci, drobnosti doladíte v závislosti na vašem softwaru.
Nginx jako reverzní proxy a TLS terminátor
Možná jste si všimli, že naše kontejnerizovaná aplikace běží na portu 8080. Abychom to celé zjednodušili a zároveň zabezpečili přístup přes HTTPS, použijeme Nginx jako hlavní reverzní proxy. Nginx zároveň zajistí terminaci TLS, takže jednotlivé aplikace se o certifikáty vůbec starat nemusejí.
Instalace Nginx
apt install nginx
Nginx bude naslouchat na standardních portech 80 a 443. V mém případě jsem ale kvůli omezením routeru musel upravit přístup z internetu, port 443 jsem nahradil portem 8443. Ty původní porty totiž používá sám router a změnit to není možné. Alespoň mi to umožňuje sem uvést příklad pro situaci, kdy se liší veřejný port od toho, který používáme interně.
Certifikáty s Let's Encrypt (Certbot)
Pro získání a obnovování TLS certifikátů jsem použil Certbot. Díky tomu nemusím řešit certifikáty manuálně – vše se obnovuje automaticky.
Na routeru jsem nastavil Port Forwarding (DNAT) takto:
- port 80 → NAS:80
- port 8443 → NAS:443
Port 80 je důležitý pro http-01 challenge, kterou používá Certbot při získávání certifikátu.
Ještě než začnete, ověřte si, že máte veřejnou IP adresu.
- Ano, statická: Super nasměrujte nas.domena.tld pomocí záznamu typu A na tuto IP.
- Ano, dynamická (můj případ): Použijte DDNS (dynamický DNS) v routeru obvykle najdete podporované služby jako No-IP, Dyn, DuckDNS atd. Následně nasměrujte host.domena.tld jako CNAME na váš DDNS hostname.
- Nemáte veřejnou IP: Bohužel přístup z internetu tím pádem nebude možný, pokud nemáte v internetu server s veřejnou adresou, přes kterou byste provoz tunelovali.
Získání TLS certifikátu
Pokud máte vše připraveno (porty, DNS, veřejná IP), nainstalujte si Certbot podle oficiálního návodu. Doporučuji si dopředu vytvořit virtuální hostitele pro každý web, který budete přes proxy publikovat. Zjednodušíte si tím další konfiguraci.
# Přechod do adresáře s konfigurací cd /etc/nginx/sites-available # Zkopírujeme výchozí konfiguraci jako šablonu cp default nas.domena.tld
Následně upravíme nový soubor:
...
listen 80;
listen [::]:80;
server_name nas.domena.tld;
...
Poté vytvoříme symbolický odkaz do aktivní konfigurace:
ln -s /etc/nginx/sites-available/nas.domena.tld /etc/nginx/sites-enabled/ systemctl restart nginx
Teď už stačí spustit samotný Certbot:
certbot --nginx -m vas@email
Certbot provede automatickou detekci, upraví konfiguraci Nginx a pokud vše proběhne správně, měli byste vidět výstup s informací o úspěšném vydání certifikátu.
Tip: Certbot automaticky nastaví i automatické obnovování certifikátu pomocí cronu nebo systemd.timer, takže se o nic nemusíte starat.
Pokud proběhne všechno dobře, měli byste vidět něco takového:
# cat /etc/nginx/sites-enabled/host.domena.tld
server {
server_name nas.domena.tld;
listen [::]:443 ssl; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/host.domena.tld/fullchain.pem; #managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/host.domena.tld/privkey.pem; #managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = nas.domena.tld) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
listen [::]:80;
server_name nas.domena.tld;
return 404; # managed by Certbot
}
Teď budeme potřebovat pro ownCloud do souboru dokonfigurovat revezní proxy. Upravíme tedy soubor /etc/nginx/sites-available/host.domena.tld a přidáme následující:
...
listen 443 ssl; # managed by Certbot
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_pass_header Authorization;
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_set_header X-Forwarded-Port 8443;
proxy_set_header X-Forwarded-Host $host:8443;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
client_max_body_size 2400M;
proxy_read_timeout 36000s;
proxy_redirect off;
}
...
V konfiguraci proxy řešíme jak proxy_pass na svůj ownCloud, tak i nastavení hlaviček. To aby ownCloud věděl, že z venku používáme https a port 8443. To jsme už zařídili na routeru v rámci přesměrování portů.
VPN
Jak jste asi pochopili, jako VPN řešení jsem zvolil WireGuard. Nastavení je jednoduché a přímočaré – žádné zbytečné složitosti – reálně to provozuji pro dva uživatele. WireGuard si dnes snadno rozběháte nejen na Linuxu, ale v podstatě na jakékoliv platformě, včetně mobilních zařízení.
Podrobný návod k instalaci najdete v oficiální dokumentaci, kde jsou dobře popsané kroky pro různé systémy. Tady si ukážeme takový rychlokurz. Pro server i klienta budete potřebovat veřejný a soukromý klíč, které si vygenerujete takto:
cd /etc/wireguard/ wg genkey | tee wg-private | wg pubkey > wg-public chmod 0600 wg-private
Tím vzniknou dva soubory – jeden se soukromým a druhý s veřejným klíčem. Na svém serveru vytvoříme konfigurační soubor /etc/wireguard/wg0.conf:
# /etc/wireguard/wg0.conf # používáme síť 10.1.0.0/24 # adresa NAS serveru Address = 10.1.0.1/24 ListenPort = 51820 PrivateKey = sem-patri-private-key # Firewall vysvětlíme v kapitole o zabezpečení # používáme UFW, věnovat se mu budeme v dalších částech seriálu PostUp = ufw route allow in on wg0 out on enp1s0; iptables -t nat -A POSTROUTING -o enp1s0 -j MASQUERADE PostDown = ufw route delete allow in on wg0 out on enp1s0; iptables -t nat -D POSTROUTING -o enp1s0 -j MASQUERADE
U částí PostUp a PostDown bych se rád krátce zastavil. Nejsou nezbytné, pokud neplánujete používat firewall, nebo nepotřebujete, aby VPN klienti přistupovali do vnitřní sítě a ven přes NAS. Pokud ano, je potřeba, aby seděly názvy rozhraní – v mém případě enp1s0 – fyzické rozhraní a wg0 – rozhraní WireGuardu.
První část ( ufw) umožní VPN klientům přístup do LAN, druhá (iptables) zajistí, aby veškerý provoz z VPN vypadal, jako by šel z NAS. Pokud vaše síť VPN klienty podporuje nativně, nemusíte to řešit.
Chcete-li přidat VPN klienta, vygenerujte jeho klíče stejným způsobem, jako u serveru. Veřejný klíč pak přidejte na NAS do wg0.conf.
Doporučuji si každý blok [Peer] okomentovat a pro každé zařízení nebo uživatele vytvořit samostatný záznam. V případě problémů snadno dohledáte, kdo měl jakou IP adresu a kdy byl připojený.
[Peer] PublicKey = sem-patri-public-key-klienta # adresa VPN klienta AllowedIPs = 10.1.0.10/32
Stav WireGuardu můžete sledovat pomocí příkazu wg:
interface: wg0
public key: VGYQPlT1XM7ZjMyqjW7X9TVTsD5NaO2z4YogNXpm7R8=
private key: (hidden)
listening port: 51820
peer: xyz
endpoint: 78.99.214.225:46774
allowed ips: 10.1.0.10/32
latest handshake: 12 hours, 29 minutes, 49 seconds ago
transfer: 564 B received, 412 B sent
Pokračování příště
V dalším článku opět přitvrdíme a podíváme se, jak z NAS monitorovat a jak z něj posílat oznámení o problémech.
Zdroje
- Všechny zdroje z článku jsou dostupné v repozitáři: github.com/rvojcik/nas-diy-resources
- dokumentace Samba
- dokumentace Docker Compose
- ownCloud.com a Nextcloud.com
- Restic Backup
- NGINX Dokumentace
- Certbot pro TLS certifikáty
- WireGuard VPN
(Autorem obrázků je Robert Vojčík.)


