Verify your declarative media server before publishing its user-facing endpoint
Nixflix brings media-service configuration into a NixOS module tree. This guide explains release pinning, configuration placement, safe rebuilds, storage and secrets, concrete HTTP checks, and remote access with Localtonet. It distinguishes verified deployment commands from release-specific installation details that the available project documentation does not establish. Once your selected application works from the device carrying tunnel traffic, you can publish that endpoint without inbound router port forwarding or a public IP address.
📋 What's in this guide
Understand the architecture and this guide’s scope
Nixflix is a NixOS media-server configuration project. Its documentation covers media applications and integrations, including Jellyfin and download-management services. It is not one monolithic web application with a universal “Nixflix port.” Each enabled application has its own listener, state, credentials, and permissions.
Jellyfin provides library browsing and playback. Request-management applications such as Seerr serve a different purpose, while tools such as Sonarr, Radarr, and Prowlarr are administrative automation interfaces. Publishing a playback interface should not also publish the services that can change libraries, download jobs, indexer settings, or API credentials.
With Localtonet, our client connects outbound to a relay and forwards requests to a selected, reachable local IP address and port. The tunnel does not install Nixflix, discover the right application automatically, or repair an unhealthy service. You choose the endpoint after verifying it.
The supplied primary evidence confirms that Nixflix v3.0.0 exists and documents its Jellyfin manifest migration. It does not contain that release’s installation instructions, exported NixOS module attribute, or option definitions. Consequently, this article cannot honestly provide a verified, copy-and-run Nixflix installation or certify the old quick example against v3.0.0. The release inspection below is an explicit prerequisite, not a claim that this missing verification has been completed. The rebuild and connectivity procedures are standard NixOS administration examples, not a reproduced official Nixflix installation sequence.
This guide narrows the NixOS configuration examples to an existing flake-managed host. It does not document channel-based or other non-flake Nixflix installation methods because the supplied project evidence does not establish their supported syntax. The practical objective is a single authenticated Jellyfin endpoint, with other integrations added only after checking their options at the same pinned revision.
Prepare the host, storage, and recovery path
Start with a functioning NixOS host that you can administer and recover. You need its existing flake directory and host output name, administrative access, sufficient build space, persistent media storage, and backups of irreplaceable state. Have console or bootloader access before testing changes that might interrupt networking or authentication. Only host and share media you are authorized to distribute.
The commands below assume Bash, an already working flake-enabled Nix installation, and the usual NixOS administration tools. HTTP checks require curl; listener inspection uses ss; source inspection uses Git. On NixOS, these diagnostic tools can be made available temporarily through your configured nixpkgs flake:
nix shell nixpkgs#curl nixpkgs#iproute2 nixpkgs#git nixpkgs#util-linux
This temporary tool environment does not install Nixflix or change the host’s services. For reproducible operational tooling, include the needed packages through your existing pinned NixOS configuration instead.
Identify the exact host configuration
Set these shell variables to your existing configuration directory and output name. media is an example, not a Nixflix requirement. Use the same values throughout the workflow.
export NIXOS_CONFIG_DIR=/etc/nixos
export NIXOS_HOST=media
cd "$NIXOS_CONFIG_DIR"
nix eval --json .#nixosConfigurations --apply builtins.attrNames
sudo nix-env --list-generations -p /nix/var/nix/profiles/system
readlink -f /run/current-system
Confirm that the intended output exists before editing. Preserve the current configuration and flake.lock in version control or a separate backup. If the flake directory is Git-managed, newly created module files must be added to Git’s tracked set before flake evaluation can include them. Review the staged files to ensure no credentials are included.
Plan persistent storage before enabling applications
Choose media and application-state locations deliberately. A path such as /data/media is only useful if the intended filesystem is mounted there when services start. A missing mount can leave an empty directory on the root filesystem, making a library appear empty or sending writes to the wrong disk.
findmnt -T /data/media
df -h /data/media
namei -l /data/media
These example paths must be replaced if your layout differs. Examine the mount source, available space, and traversal permissions on every parent directory. Declare persistent mounts in NixOS rather than relying on a desktop login to mount an external drive. Keep the service account minimally privileged instead of granting access to an entire personal home directory.
Separate secrets from the Nix store
API integrations may require runtime credential files. Declaring a file path does not provision that file. Your secret-management system must create it before the consuming unit starts, with ownership and permissions appropriate to that unit. Files under /run generally need to be recreated after a reboot.
Do not embed credentials in Nix expressions, use secret-bearing files as ordinary Nix source inputs, or commit them with the configuration. The Nix store is not a secret store. Keep application keys, administrator passwords, and Localtonet device tokens separate. When debugging, inspect file metadata and unit logs rather than printing secret contents.
Pin and inspect the Nixflix release before module inclusion
The verified release available for this revision is Nixflix v3.0.0. Its release page identifies commit prefix b8a60e8 and explains that the Jellyfin manifest moved into the main repository after the former repository was deleted. This establishes a migration consideration, not that v3.0.0 is the newest release or compatible with every NixOS version.
The following is a valid standard Nix flake source declaration for that published tag. Add it inside your existing flake’s inputs attribute set; do not replace the rest of your host flake:
nixflix.url = "github:kiriwalawren/nixflix/v3.0.0";
Then resolve the input and inspect the lock-file change:
cd "$NIXOS_CONFIG_DIR"
nix flake lock
git diff -- flake.nix flake.lock
The lock file records the resolved source revision and content hash. Preserve it with the configuration. Do not add a nixpkgs.follows override merely because it appears in an unrelated example: the compatibility requirements of this release have not been established here.
Inspect the release rather than guessing its module export
You can inspect the pinned source and its public outputs with the following commands. These are source-discovery commands, not proof of a supported installation path:
nix flake metadata github:kiriwalawren/nixflix/v3.0.0
nix flake show github:kiriwalawren/nixflix/v3.0.0
git clone --branch v3.0.0 --depth 1 \
https://github.com/kiriwalawren/nixflix.git nixflix-v3-source
git -C nixflix-v3-source rev-parse HEAD
git -C nixflix-v3-source ls-tree --name-only HEAD
sed -n '1,240p' nixflix-v3-source/flake.nix
Use a separate working directory for this inspection checkout. Check the release’s README and documentation files for the installation instructions, required inputs, module export, and host options. The current website’s extensive navigation does not establish which features existed in v3.0.0. Similarly, a module output found through inspection must still be reconciled with the release’s instructions rather than selected because its name looks conventional.
The evidence supplied here does not establish whether this release exports nixosModules.default, a differently named module, or another installation interface. No exact module reference can be responsibly supplied without inspecting that source. Stop before activation until the export and supported options have been confirmed. A source input alone does not make the nixflix option available.
Place configuration in the intended host’s module tree
After confirming the installation interface, add the exact documented Nixflix module reference to the existing modules list of your intended nixpkgs.lib.nixosSystem host. Ensure that the flake input is accessible in that outputs function. Keep hardware configuration, boot settings, filesystems, and existing modules intact.
A separate host configuration file can live at /etc/nixos/nixflix-host.nix. Import that file from the host’s existing configuration.nix by adding the following entry to its existing imports list:
./nixflix-host.nix
This local import is ordinary NixOS module placement. It does not replace inclusion of the project’s exported module. In a multi-host flake, load both only for the media host unless other machines intentionally need them.
Do not treat the former quick example as release-validated
The previous version of this article included nixflix.enable, mediaDir, stateDir, service enable flags, and _secret values for Sonarr, Prowlarr, and SABnzbd. The supplied current extracts do not include the corresponding option definitions at v3.0.0. That configuration is therefore not reproduced as an executable, verified starter.
Confirm the minimal Jellyfin declaration first, including defaults that might enable other services or listeners. Add request management, download clients, plugins, reverse proxies, or database integration only after checking the same release’s options and examples. The Nixflix option reference and project examples are useful supplements, but do not assume their current contents match an older pinned release.
For comparison, the supplied official NixOS Jellyfin guidance independently establishes services.jellyfin.enable = true; as a standard Jellyfin installation option. That is a different deployment path, not a substitute that can be labeled a completed Nixflix installation. Avoid combining both approaches until their interaction is understood.
Evaluate, build, test, activate, and recover
Continue only after completing the release-specific module and option verification. The following commands target the existing flake host explicitly. They are standard NixOS lifecycle commands, not an invented eight-step Nixflix product workflow.
Evaluate and build without activating
cd "$NIXOS_CONFIG_DIR"
nix eval --raw \
".#nixosConfigurations.${NIXOS_HOST}.config.system.build.toplevel.drvPath"
sudo nixos-rebuild build \
--flake "${NIXOS_CONFIG_DIR}#${NIXOS_HOST}"
Evaluation catches module errors, missing attributes, and assertions. Building realizes the system closure without switching the running services. Neither operation proves that a runtime secret exists, an application database is usable, or a media mount contains the expected files.
Test the generation on the running host
Before testing, record the current system path and keep the terminal or another administrative session open:
export PREVIOUS_SYSTEM="$(readlink -f /run/current-system)"
sudo nixos-rebuild test \
--flake "${NIXOS_CONFIG_DIR}#${NIXOS_HOST}"
systemctl --failed --no-pager
test activates the new system for the current session without making it the boot default. It is not a sandbox or a dry run: services can restart and applications can write persistent state or migrate databases. Back up state before testing an upgrade, and use console access if loss of connectivity would prevent recovery.
Make the checked configuration persistent
Complete the service, storage, HTTP, and authentication checks in the next section. If they pass, activate the same reviewed configuration persistently:
sudo nixos-rebuild switch \
--flake "${NIXOS_CONFIG_DIR}#${NIXOS_HOST}"
Do not change the lock file or configuration between testing and switching without repeating validation. Retain the previous generation until the new stack has passed representative playback and integration checks.
Recover from a failed test or switch
To undo a test activation within the same shell, the previously recorded system path can reactivate the prior runtime configuration:
sudo "$PREVIOUS_SYSTEM/bin/switch-to-configuration" test
After a persistent switch, the usual previous-generation rollback is:
sudo nixos-rebuild switch --rollback
If you cannot access the running system, select a known-good generation from the bootloader where available. A generation rollback does not restore application databases, media, deleted files, or secret contents. Restore application state from a compatible backup when necessary. Also restore or correct the declarative configuration and lock file, otherwise a future rebuild can reintroduce the failure.
Inspect services, discover listeners, and test HTTP
Check application and configuration units
systemctl --failed --no-pager
sudo systemctl status jellyfin.service --no-pager
sudo journalctl -u jellyfin.service -b -n 100 --no-pager
systemctl list-unit-files --type=service --no-pager \
| grep -Ei 'nixflix|jellyfin|sonarr|radarr|prowlarr|seerr'
The last command helps discover installed unit names; it does not guarantee that every configuration unit contains one of those strings. Inspect the exact failed units reported by systemd. An application process can be healthy while a separate API configuration unit has failed because of credentials, readiness, or dependency ordering.
Discover the actual bind address and port
sudo ss -ltnp
sudo systemctl cat jellyfin.service
sudo systemctl show jellyfin.service -p User -p Group
Find the application or proxy listener in the output. 127.0.0.1 is loopback and cannot be reached directly from another machine. A wildcard or LAN bind may be reachable, subject to firewall and routing policy. Do not assume an IPv6 listener necessarily accepts IPv4 connections.
Standard NixOS Jellyfin uses port 8096 by default. Treat it as a candidate to confirm, not a universal Nixflix endpoint. For a confirmed local HTTP listener, run:
curl --connect-timeout 5 --max-time 15 \
-sS -D - -o /dev/null http://127.0.0.1:8096/
A response proves that something answered HTTP. A redirect may be normal; a 401 or 403 indicates an authorization decision rather than a connection failure. Inspect the headers and use a browser to confirm application identity, sign-in, library permissions, and playback. Do not automatically follow an unexpected redirect before checking its destination.
Test from the Localtonet client device
Run this from the device that will run our client, replacing the example private address and port with your verified target. On Windows, use curl.exe if needed to invoke curl rather than a shell alias.
curl --connect-timeout 5 --max-time 15 \
-sS -D - -o /dev/null http://192.168.1.50:8096/
A successful loopback check on NixOS does not establish this second path. If it fails, inspect the listener binding, LAN routing, host firewall, and network policy. Permit only the necessary traffic from the client device where possible. Do not disable the firewall or open every media-management port.
Check host-based reverse-proxy routing
If the target is a reverse proxy, a request to its IP may return a default site. For a confirmed plain-HTTP proxy listener, test the hostname it expects:
curl --connect-timeout 5 --max-time 15 \
-sS -D - -o /dev/null \
-H 'Host: media.example.test' http://192.168.1.50:80/
The address, hostname, and port here are examples. This diagnostic does not configure Localtonet to rewrite host headers. Before tunneling the proxy, ensure its routing handles the public request intentionally. For HTTPS upstream testing, certificate identity and TLS server-name selection also matter; do not hide those problems by disabling certificate verification.
The supplied evidence does not establish a native Localtonet installation method for NixOS. Use a currently supported client device that can reach the NixOS endpoint, unless our current documentation confirms a NixOS-compatible installation method. An installer for another Linux distribution is not proof of NixOS compatibility.
Choose the smallest useful public endpoint
| Endpoint | Purpose | Exposure decision |
|---|---|---|
| Jellyfin | Library browsing and playback | Use authenticated, limited accounts and test representative media. |
| Seerr, if deployed | Media requests | Prefer a request-only interface when streaming access is unnecessary. |
| Existing reverse proxy | Routing to an application | Verify host, path, upstream, and trusted-header behavior. |
| Sonarr, Radarr, or Prowlarr | Administrative automation | Keep private by default because these interfaces control sensitive operations. |
A proxy does not automatically make a broad stack safe to expose. Check whether its public hostname also serves administration routes or other applications. Publish only the route users need, with authentication in place before the tunnel starts. Where a private administrative network is more appropriate, evaluate a separate private-access design instead of treating an ordinary HTTP tunnel as a VPN.
Connect the verified endpoint with Localtonet
For the selected browser-facing HTTP service, use an HTTP tunnel. Our client establishes an outbound relay connection, so internet access does not require inbound router port forwarding, VPN setup, or a public IP address. A separate client device still needs permission and network reachability to contact the NixOS host.
Install and run the client on a supported device
Choose a device that can remain online and has passed the target HTTP check. Use the current installation instructions for its operating system.
Authenticate the selected device
Use its device-specific authentication token. Keep the token out of public repositories, application configuration, screenshots, and shared logs.
Select an available relay server
Choose a currently available server or region from our dashboard. Do not copy a hardcoded server code from another deployment.
Create the HTTP configuration
Set the local target IP address and port to the values verified from the client device. Use loopback only when the target is on that same device. Select an available HTTP Process Type for the public address.
Start and verify the tunnel
Press Start, then open the assigned public HTTPS address from an external connection. Check application identity, sign-in, permissions, navigation, and playback or request submission.
Stop or delete access when no longer needed
Stop the tunnel to end access while retaining its configuration, or delete it when no longer required. Availability requires both a connected client and a running tunnel.
Our HTTP tunnel documentation provides the current dashboard workflow. HTTP Process Types include Random Sub Domain, Custom Sub Domain, and Custom Domain. Check current availability and custom-domain DNS requirements rather than assuming every option is included in every subscription.
Harden the service before sharing its address
A public URL is reachability, not authorization. Complete initial application setup before starting the tunnel. Use individual accounts, strong credentials, and the narrowest library and management permissions each user needs. Never share an administrator account for routine playback.
Keep download clients, databases, indexer management, operating-system administration, and secret-management interfaces private. Review reverse-proxy routes for accidental exposure of additional services. If applications use forwarded host, scheme, or client-address headers, trust only the legitimate proxy path rather than arbitrary network clients.
Verify the public HTTPS address from outside the LAN without certificate warnings. Check that redirects and generated links remain on the intended external hostname rather than leaking a LAN address. Public HTTPS should not be interpreted as proof of the security properties of every internal connection; assess the client-to-target network separately.
Keep NixOS, applications, Nixflix, and the client maintained. Pinning makes changes controlled; it does not replace security updates. Review application plugins individually before enabling them, since a long option catalog is not a reason to install unnecessary extensions.
Monitor upload capacity, storage throughput, CPU or GPU load, account activity, and application logs. Remote playback can trigger transcoding even when a local browser direct-plays the same file. Stop the tunnel if an incorrect route, compromised account, vulnerable application, or unexpected traffic is discovered.
Operate and update the deployment in separate layers
Keep configuration, lock files, runtime secrets, application databases, media, and tunnel settings as separate recovery concerns. Back up state using an application-appropriate method that produces consistent databases. Test restoration rather than assuming that copying an active database is sufficient.
| Change | Checks | Recovery concern |
|---|---|---|
| NixOS or Nixflix update | Release notes, lock diff, evaluation, build, test, failed units | Older binaries may not understand migrated application state. |
| Storage change | Mount source, space, traversal, service-account access | System rollback does not restore missing media. |
| Secret rotation | Runtime file provisioning and integration authentication | Credential state is independent of a system generation. |
| Proxy or tunnel change | Local HTTP, client reachability, public routing and sign-in | Stop exposure while correcting an unintended route. |
Avoid combining storage migrations, proxy redesign, and application upgrades into one deployment. After each change, work outward: failed units, local HTTP, client-to-target HTTP, then public HTTPS. After a reboot, repeat checks for transient secrets, persistent mounts, and client connectivity.
Keep known-good generations and backups until recovery has been tested. Do not edit generated files in the Nix store to repair a deployment; make durable corrections in the source configuration. Where Nixflix manages an application setting declaratively, account for possible reapplication before making a conflicting change through the application interface.
Troubleshoot by the first failing layer
The nixflix option does not exist
Check that the release source is available, its verified module export is included in the intended host, and the host configuration file is imported. A new untracked file in a Git-backed flake can also be absent from evaluation. Do not “fix” this by guessing another module attribute.
Evaluation fails after a dependency update
Review the lock-file diff and release-specific options. Current online examples may not match the pinned revision. For migrations involving v3.0.0, account for the documented Jellyfin manifest-source change. Restore the reviewed source and lock state if necessary before attempting a smaller update.
A configuration unit fails while Jellyfin runs
Inspect that exact unit’s journal. Distinguish application readiness from credential, dependency, or API configuration failure. Verify secret-file existence and access without printing the key. Correct the declaration or secret provisioning before retrying.
Jellyfin cannot read media
Check findmnt, df, and parent-directory permissions. After confirming the service account, test a representative file as that account. For the standard account, an example is:
sudo -u jellyfin test -r /data/media/example.mp4 \
&& printf 'Media file is readable\n'
Replace the filename with a real file. Do not recursively loosen permissions across a disk or switch the service to an unrestricted desktop account as a shortcut.
Local HTTP works, but the client device cannot connect
Inspect the bind address with ss. A refusal often indicates no accepting listener or an active rejection; a timeout can indicate filtering or routing trouble. Check the actual LAN address and narrow firewall policy. Remember that localhost on the client is the client itself.
The proxy serves the wrong site
Compare an IP-based request with the expected Host-header request. Verify the upstream independently. Correct host and path routing before changing tunnel targets repeatedly, and do not assume a diagnostic custom header represents the public request behavior.
The tunnel exists but the public URL fails
Confirm that the selected device is connected and the tunnel has been started. Retest the configured target from that device. A NixOS rebuild may have changed a listener or firewall rule even if the tunnel configuration did not change.
Login succeeds but remote playback fails
Test a small direct-play file and a file that requires transcoding. Inspect Jellyfin logs, permissions, storage, and resource use. Compare local and public playback with the same account. A successful landing page does not test the bandwidth or media-processing path.
Frequently asked questions
Is this a verified copy-and-run Nixflix v3.0.0 installation?
No. The available evidence verifies the release and migration note but does not include its exported module reference or option definitions. Those remain an explicit verification prerequisite. The article provides source inspection, standard flake rebuild commands, recovery procedures, and concrete endpoint checks without inventing the missing installation syntax.
Does the entire Nixflix stack use port 8096?
No. Port 8096 is the standard Jellyfin HTTP default. Other applications and reverse proxies have separate listeners. Use the endpoint observed on your host and successfully tested from the Localtonet client device.
Does Localtonet require router port forwarding?
No. Our client connects outbound to a relay. A separate LAN client still needs a permitted route to the NixOS service, including any necessary narrow host-firewall rule.
Can the Localtonet client run directly on NixOS?
A verified native NixOS installation path is not established here. Use a currently supported client device with access to the target unless current Localtonet documentation explicitly confirms the required installation method.
Does NixOS rollback restore the media database?
No. System-generation rollback restores the system configuration and software generation, not arbitrary mutable application state. Maintain compatible backups of databases, secrets, and irreplaceable media before upgrades.
Will creating a tunnel immediately make the service public?
No. The selected client must be connected, the tunnel must be started, and the target must be reachable. Stop or delete the tunnel when access is no longer required.
Connect a verified media endpoint with Localtonet
Complete release-specific module verification, test your application from a supported client device, and publish only the authenticated interface your users need. Keep the rest of the stack private and stop the tunnel when remote access is unnecessary.
Get Started Free →