Stavíme vlastní NAS: konfigurace služeb na síťovém úložišti

17. 9. 2025
Doba čtení: 14 minut

Sdílet

Skříň vlastního síťového úložiště NAS
Autor: Robert Vojčík
Stavba vlastního síťového úložiště (NAS) nemusí být drahá ani složitá. V dnešním článku se podíváme blíž na to, jak připravit a nakonfigurovat základní služby, které od svého řešení chceme.

Služby na NAS

Co se dozvíte v článku
  1. Služby na NAS
  2. Samba a sdílení souborů
  3. Přístup z internetu
  4. Jak nasazovat a spravovat aplikace?
  5. Web UI a mobilní aplikace
  6. Zálohování MariaDB
  7. Nginx jako reverzní proxy a TLS terminátor
  8. VPN
  9. Pokračování příště
  10. Zdroje

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-server zí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).
Stavíme NAS

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.

Stavíme NAS

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.

Stavíme NAS

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

(Autorem obrázků je Robert Vojčík.)

Neutrální ikona do widgetu na odběr článků ze seriálů

Zajímá vás toto téma? Chcete se o něm dozvědět víc?

Objednejte si upozornění na nově vydané články do vašeho mailu. Žádný článek vám tak neuteče.


Autor článku

Studoval na Fakultě elektrotechnické ČVUT. Mezi jeho oblíbené technologie patří Kubernetes, Proxmox, CEPH a Puppet. Ve volném čase se věnuje elektronice, 3D tisku a příležitostně vystupuje na konferencích.