Table of Contents
Pi-Hole - Setup Pi-Hole running in LXC
Create an LXC Container
lxc init ubuntu:20.04 pihole
returns:
Creating pihole
Check the status
lxc info pihole
returns:
Name: pihole Location: none Remote: unix:// Architecture: x86_64 Created: 2021/01/03 20:40 UTC Status: Stopped Type: container Profiles: default
Start the Container
lxc start pihole
Check the status again
lxc info pihole
returns:
Name: pihole Location: none Remote: unix:// Architecture: x86_64 Created: 2021/01/03 20:40 UTC Status: Running Type: container Profiles: default Pid: 844849 Ips: eth0: inet 10.207.221.25 vethd19000f6 eth0: inet6 fd42:4242:fe05:c96b:216:3eff:fecd:bd67 vethd19000f6 eth0: inet6 fe80::216:3eff:fecd:bd67 vethd19000f6 lo: inet 127.0.0.1 lo: inet6 ::1 Resources: Processes: 76 CPU usage: CPU usage (in seconds): 10 Memory usage: Memory (current): 419.70MB Memory (peak): 462.38MB Network usage: eth0: Bytes received: 779.53kB Bytes sent: 20.10kB Packets received: 195 Packets sent: 201 lo: Bytes received: 1.68kB Bytes sent: 1.68kB Packets received: 19 Packets sent: 19
NOTE: This shows the container is running.
It also shows it has an IP address of 10.207.221.25, which is probably not what is wanted as this is different from the host subnet range.
Assign the bride profile to the container
IMPORTANT: Do NOT use the macvlan profile as it does not allow the host to access the Container.
Every other device can access the Container, just not the host, unless the host is placed into Promiscuous mode.
See: Make your LXD containers get IP addresses from your LAN using macvlan
lxc profile assign pihole default,bridgeprofile
returns:
Profiles default,bridgeprofile applied to pihole
NOTE: The assign command must have both the default and bridgeprofile profiles as shown.
Check the status once again
lxc info pihole
returns:
Name: pihole Location: none Remote: unix:// Architecture: x86_64 Created: 2021/01/03 20:40 UTC Status: Running Type: container Profiles: default, bridgedprofile Pid: 844849 Ips: eth0: inet 192.168.1.150 br0 eth0: inet6 fe80::216:3eff:fe38:3c04 br0 lo: inet 127.0.0.1 lo: inet6 ::1 Resources: Processes: 79 CPU usage: CPU usage (in seconds): 10 Memory usage: Memory (current): 427.35MB Memory (peak): 462.38MB Network usage: eth0: Bytes received: 1.29kB Bytes sent: 1.47kB Packets received: 11 Packets sent: 11 lo: Bytes received: 1.68kB Bytes sent: 1.68kB Packets received: 19 Packets sent: 19
NOTE: The IP address has changed to 192.168.1.150.
This is the correct subnet matching that of the host.
If the result does not show an IP for eth0, then just wait a few seconds and retry. It seems to take a while sometimes before the container picks up the change. Do not panic if this continues to not show. Just continue with the steps.
Set the default login password
lxc exec pihole -- passwd ubuntu New password: Retype new password: passwd: password updated successfully
NOTE: There is a default user account named ubuntu, which is being used here.
You could setup a completely different user account if wanted.
NOTE: An alternative way to do this is by:
lxc exec pihole -- /bin/bash
Then to issue the following command, and enter a secure password:
passwd ubuntu
Set up a proxy to allow web traffic into the LXD container (Optional)
On the host, not the container, add a proxy:
lxc config device add pihole web proxy listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80
returns:
Device web added to pihole
NOTE: Ensure that the Container is stopped before running this.
If this fails, then not a worry and may not be needed. You may get an error such as
Error: Failed to start device "web": Error occurred when starting proxy device: Error: Failed to listen on 0.0.0.0:80: listen tcp 0.0.0.0:80: bind: address already in use
Get a Shell inside the Container
lxc exec pihole bash
NOTE: Alternatively try:
lxc console pihole
returns:
To detach from the console, press: <ctrl>+a q
NOTE: Press <ENTER>.
pihole login: ubuntu Password:
NOTE: Enter ubuntu for the login and use the password you set for that account.
This should then log you into a standard ubuntu system:
Welcome to Ubuntu 20.04.1 LTS (GNU/Linux 5.4.0-58-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage System information as of Sun Jan 3 20:57:34 UTC 2021 System load: 2.2 Temperature: 37.0 C Usage of /home: unknown Processes: 24 Memory usage: 0% Users logged in: 0 Swap usage: 0% IPv4 address for eth0: 192.168.1.148 1 update can be installed immediately. 0 of these updates are security updates. To see these additional updates run: apt list --upgradable The list of available updates is more than a week old. To check for new updates run: sudo apt update The programs included with the Ubuntu system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. To run a command as administrator (user "root"), use "sudo <command>". See "man sudo_root" for details.
Check the Network
Ensure that LXC is configured properly; i.e. that it is able to access the internet.
ip a
returns:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 20: eth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 00:16:3e:38:3c:04 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 192.168.1.150/24 brd 192.168.1.255 scope global dynamic eth0 valid_lft 6056sec preferred_lft 6056sec inet6 fe80::216:3eff:fe38:3c04/64 scope link valid_lft forever preferred_lft forever
NOTE: The eth0 interface does show it has an IP address which is part of the host subnet, i.e. 192.168.1.150.
Try to ping.
ping 192.168.1.1 -c 1
returns:
PING 192.168.1.1 (192.168.1.1) 56(84) bytes of data. 64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=0.410 ms --- 192.168.1.1 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.410/0.410/0.410/0.000 ms
NOTE: Change the ping address as needed to the correct subnet.
If the ping fails, then try to restart networking on the container:
netplan apply
Configure an IP on the Container
Pi-Hole needs a static IP, so set one.
By default the Container uses DHCP, so each time it starts it would receive a different IP.
- vi /etc/netplan/50-cloud-init.yaml
# This file is generated from information provided by the datasource. Changes # to it will not persist across an instance reboot. To disable cloud-init's # network configuration capabilities, write a file # /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following: # network: {config: disabled} #network: # version: 2 # ethernets: # eth0: # dhcp4: true # # Let NetworkManager manage all devices on this system network: version: 2 #renderer: NetworkManager renderer: networkd ethernets: eth0: dhcp4: no # disable existing configuration for ethernet addresses: [192.168.1.150/24] gateway4: 192.168.1.1 nameservers: addresses: [192.168.1.1] dhcp6: no
NOTE: This sets a static IP address, which is needed for Pi-Hole.
The default dhcp has been commented out, but can be deleted from this file.
The actual netplan filename may be slightly different; Edit the actual filename within the /etc/netplan directory.
Apply the network changes
netplan apply
Exit the Shell
exit
Restart the Pi-Hole Container
lxc restart pihole
Try to ping the Pi-Hole Container from the Host
ping 192.168.1.150
returns:
PING 192.168.1.150 (192.168.1.150) 56(84) bytes of data. 64 bytes from 192.168.1.150: icmp_seq=1 ttl=64 time=0.031 ms 64 bytes from 192.168.1.150: icmp_seq=2 ttl=64 time=0.027 ms 64 bytes from 192.168.1.150: icmp_seq=3 ttl=64 time=0.026 ms 64 bytes from 192.168.1.150: icmp_seq=4 ttl=64 time=0.044 ms 64 bytes from 192.168.1.150: icmp_seq=5 ttl=64 time=0.028 ms --- 192.168.1.150 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4101ms rtt min/avg/max/mdev = 0.026/0.031/0.044/0.006 ms
NOTE: If this step fails, bash back into the container
lxc exec pihole bash
and then restart the network:
netplan apply
Then exit and retry the ping and if that works you should be able to access Pi-Hole from the web.
Get a Shell inside the Container
lxc exec pihole bash
Update the Container
sudo apt update sudo apt upgrade
Install additional packages
sudo apt install cron curl wget openssh-server vim ca-certificates
NOTE: Some of these additional packages may already be installed. Not a concern.
The ca-certificates package is needed to prevent errors later with curl.
Without this, errors such as: curl: (60) SSL certificate problem: unable to get local issuer certificate may be seen.
Of course, this package, as well as any other package can be installed later with commands such as:
apt install ca-certificates
Install Pi-Hole
sudo curl -sSL https://install.pi-hole.net | bash
or
curl -sSL https://install.pi-hole.net -o pihole.sh
NOTE: The 2nd option here just downloads the script. It does not actually install Pi-Hole until it is run.
This is a little safer, as it allows you to check the code in the script against trojans etc. Once you are sure it is okay then run:
sudo bash pihole.sh
Select the defaults until the DNS screen and then choose Cloudflare as your DNS.
- Accept all the rest of the defaults and be careful not to change them. This will assure that you get the admin web interface and that statistics are logged.
- The installation will continue for a few minutes after you answer the prompts.
- After your installation completes, you will receive a message telling you to set up the DHCP settings on your router to make the address of your Pi-Hole the primary DNS for your network.
- That will insert the Pi-Hole as the “man-in-the-middle” to scrutinize all DNS names before they are either passed to the Internet or “Pi-Holed”.
NOTE: If an error occurs, then either fix the firewall rules or try:
curl -sSL https://install.pi-hole.net | PIHOLE_SKIP_OS_CHECK=true sudo -E bash
Set the Pi-hole password
When you return to the prompt in the terminal session, enter the following command to set your Pi-hole password:
pihole -a -p
Try to access Pi-Hole from a Web Browser
192.168.1.150
IMPORTANT: Make sure that the URL you type is does NOT contain https:// in front of the IP Address.
NOTE: If this fails, then try to access it from a different device than the host.
If this works, then mostly good. Primary reason host cannot access is that the network needs to run in Promiscuous mode.
Configure Promiscuous mode then retry.
An alternative option is to use a Bridged Profile.
Exit the Pi-Hole Container
exit
Get Information on the Pi-Hole Container
lxc info pihole
returns:
Name: pihole Location: none Remote: unix:// Architecture: x86_64 Created: 2021/01/07 14:59 UTC Status: Running Type: container Profiles: default, bridgeprofile Pid: 708446 Ips: eth0: inet 192.168.1.150 vethb3f914e9 eth0: inet6 fe80::216:3eff:fecb:fcf8 vethb3f914e9 lo: inet 127.0.0.1 lo: inet6 ::1 Resources: Processes: 88 CPU usage: CPU usage (in seconds): 20 Memory usage: Memory (current): 266.82MB Memory (peak): 276.11MB Network usage: eth0: Bytes received: 2.45MB Bytes sent: 3.70MB Packets received: 18537 Packets sent: 3905 lo: Bytes received: 4.05MB Bytes sent: 4.05MB Packets received: 60882 Packets sent: 60882
TIP: If this still does not work, then perhaps delete the Pi-Hole Container and restart.
lxc delete pihole lxc profile delete macvlan lxc profile delete bridgeprofile
No need to delete the profiles if you are happy with these. Just delete the actual Container and follow the steps above.
Have the LXC Container Start Automatically
By default, LXC containers may not start automatically.
lxc config set pihole boot.autostart true
Ensure that LXC is set to start containers at boot.
- /etc/default/lxc
# LXC_AUTO - whether or not to start containers at boot LXC_AUTO="true"
NOTE: Also check file /etc/default/lxc-net, just in case this overrides this setting.
NOTE: Autostart is mainly used to select which containers to start.
When the host system boots, LXC decides the order and the delay between each startup.
Show the Pi-Hole Container Configuration File
lxc config show pihole
returns:
architecture: x86_64 config: boot.autostart: "true" image.architecture: amd64 image.description: ubuntu 20.04 LTS amd64 (release) (20210105) image.label: release image.os: ubuntu image.release: focal image.serial: "20210105" image.type: squashfs image.version: "20.04" volatile.base_image: 21da67063730fc446ca7fe090a7cf90ad9397ff4001f69907d7db690a30897c3 volatile.eth0.host_name: veth9b7de9bd volatile.eth0.hwaddr: 00:16:3e:4c:1b:d7 volatile.idmap.base: "0" volatile.idmap.current: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]' volatile.idmap.next: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]' volatile.last_state.idmap: '[{"Isuid":true,"Isgid":false,"Hostid":1000000,"Nsid":0,"Maprange":1000000000},{"Isuid":false,"Isgid":true,"Hostid":1000000,"Nsid":0,"Maprange":1000000000}]' volatile.last_state.power: RUNNING volatile.uuid: 10e59167-cf89-4919-bb1c-9e701d15e08c devices: {} ephemeral: false profiles: - default - bridgeprofile stateful: false description: ""
NOTE: This file will not be created until a change is made to it.
In this case, the autostart config done previously has enabled this.