Running a local dns and web server
Tags: dns, nix, webserver
Published: 2020-06-24 21:19:23

---
title: Running a local dns and web server
published: true
date: 2020-06-24 00:00:00 UTC
tags: dns,nix,webserver
canonical_url: https://www.lafuente.me/posts/local-dns-and-web-server
---

As a software developer, I run multiple web services to be accessed only from localhost. While it is possible to access them on `http://localhost`, I prefer to have more descriptive urls, like `http://docs.local`.

 

I'm going to describe my [NixOS](https://nixos.org/) setup to resolve `.local` domains to localhost and access my local web server. I'm using [CoreDNS](https://coredns.io/) and [Caddy](https://caddyserver.com/) to accomplish it. Keep in mind that while I'm showing nix configuration snippets, you could extract the configuration files and run a similar setup in any Linux distribution.

 

It is interesting to notice that [CoreDNS](https://coredns.io/) started its life as a fork of [Caddy](https://caddyserver.com/).

 
# DNS server [#](#dns-server)
 

While I could use [dnsmasq](http://www.thekelleys.org.uk/dnsmasq/doc.html), I wanted to try a newer DNS server, [CoreDNS](https://coredns.io/). Let's start the service with some custom configuration:

 
```
services.coredns.enable = true;services.coredns.config = '' . { # Cloudflare and Google forward . 1.1.1.1 1.0.0.1 8.8.8.8 8.8.4.4 cache } local { template IN A { answer "{{ .Name }} 0 IN A 127.0.0.1" } } '';
```
 

The first block will forward all the DNS requests to Cloudflare and Google DNS servers, and the results will be cached (1 hour by default)

 

The second block returns an A record with value `127.0.0.1` for any request for a `.local` domain.

 

So far, so good, we have a local DNS server up and running. Now we need to configure our network manager to use that DNS server. If you are on [NixOS](https://nixos.org/), that's pretty easy:

 
```
networking.networkmanager.insertNameservers = ["127.0.0.1"];
```
 
# Web server [#](#web-server)
 

I could use [nginx](https://nginx.org/en/docs/), but I decided to use [Caddy](https://caddyserver.com/) instead because it comes with an HTTP API out of the box. I'm not explaining it in this post, but [Caddy](https://caddyserver.com/)'s API opens the door to many interesting possibilities.

 

Let's take a look our `Caddyfile` configuration:

 
```
http://docs.local { root * /path/to/dir file_server } 
```
 

Here we are saying that all requests to `http://docs.local` should serve static files located at `/path/to/dir`.

 

Until [#86686](https://github.com/NixOS/nixpkgs/pull/86686) is merged, you need to create your own systemd unit to start [Caddy](https://caddyserver.com/):

 
```
let caddyConfig = pkgs.writeText "Caddyfile" '' http://docs.local { root * /path/to/dir file_server } '';in{ systemd.services.caddy = { description = "Caddy web server"; after = ["network-online.target"]; wants = ["network-online.target"]; wantedBy = ["multi-user.target"]; serviceConfig = { User = "caddy"; Group = "caddy"; ExecStart = '' ${pkgs.caddy2}/bin/caddy run --config ${caddyConfig} --adapter caddyfile ''; ExecReload = '' ${pkgs.caddy2}/bin/caddy reload --config ${caddyConfig} --adapter caddyfile ''; TimeoutStopSec = "5s"; LimitNOFILE = 1048576; LimitNPROC = 512; PrivateTmp = true; ProtectSystem = "full"; AmbientCapabilities = "cap_net_bind_service"; }; }; users.users.caddy = { group = "caddy"; uid = config.ids.uids.caddy; home = caddyDir; createHome = true; extraGroups = ["users"]; }; users.groups.caddy.gid = config.ids.uids.caddy;}
```