Installing Znc on Freebsd With Ansible
I’ve never really used ansible before, and rarely get to play with freebsd so when I needed to setup a new IRC bouncer I decided what better chance than now to have a play. Although there are some built-in ansible modules for working with the ports system (Which is what we are going to use to install znc), they aren’t yet complete enough to bootstrap a server from scratch.
We first need to setup our local computer to allow us to connect to the freebsd server. I recommend setting up and copying ssh keys to the server before continuing as it’ll make your life much easier (and more secure if you disable password authentication).
Start by adding the irc bouncing server to /etc/ansible/hosts
, if this is your only server, the file will look something like:
root@ircbouncer.mydomain.com
You can confirm this worked by running
# ansible all -m ping
Once you are all connected and authenticated to your server, we can start building the ansible playbook to install znc.
As I mentioned, we’ve got to do a few manual steps in the playbook to bootstrap the server ready to use the port install built-in functionality. Namely, we need to do an initial download, and then make sure the tree is up to date.
---
- hosts: all
tasks:
- name: initialize ports db
command: portsnap fetch extract
args:
creates: /usr/ports
- name: update ports db
command: portsnap fetch update
This runs portsnap fetch extract
only if /usr/ports
doesn’t already exist. It then runs portsnap fetch update
on every ansible run to make sure that we keep our ports tree up to date. This doesn’t take too long as it’s only an incremental operation.
Once we’ve bootstrapped our ports tree and made sure it’s up to date, we can use the built-in functionality for installing the znc bouncer.
- name: install znc
portinstall:
name: irc/znc
state: present
Side note: I ran the above on a 1-core VPS from Vultr and was surprised how long the compiling took. All said an done it ended up being in the region of 2-3 hours. If you think you are likely to lose connection in that time, I highly recommend holding off running ansible playbook until you are on a stable internet connection. Alternatively, ssh to a desktop/server and use a terminal multiplexer (tmux/screen) to keep your session running even if you disconnect.
We also need to configure znc. For the time being, I’m just to install znc but leave management to the web interfce and commands (which is actually the officially recommended way). However, even with this method you still need to initialize the config. Unfortunately there doesn’t seem to be an unattended option when using znc --makeconfig
so instead we must create it from scratch ourselves. We can take the created file and create a ansible template with it, as follows. This should be saved in a separate file called znc.conf.tmpl
// WARNING
//
// Do NOT edit this file while ZNC is running!
// Use webadmin or *controlpanel instead.
//
// Altering this file by hand will forfeit all support.
//
// But if you feel risky, you might want to read help on /znc saveconfig and /znc rehash.
// Also check https://wiki.znc.in/Configuration
Version = 1.7.5
<Listener l>
Port = {{ listen_port }}
IPv4 = true
IPv6 = true
SSL = false
</Listener>
LoadModule = webadmin
<User {{ user_name }}>
Pass = sha256#{{ user_passhash }}#
Admin = true
Nick = {{ user_nick }}
AltNick = {{ user_altnick }}
Ident = {{ user_ident }}
RealName = {{ user_realname }}
</User>
We then need to install that file only when it doesn’t already exist (Which allows us to initialize it but then ignore any further changes). We do that by first stat
ting the file and then using that as a when
parameter to the template instantiation.
- stat: path=/usr/local/etc/znc/configs/znc.conf
register: config_file_stat
- template: src=znc.conf.tmpl dest=/usr/local/etc/znc/configs/znc.conf
when: not config_file_stat.stat.exists
The finishing touche to the config initialization is to pass those parameters in. Just below the -hosts: all
at the top of our file, we need a new vars entry containing the variables:
vars:
listen_port: 8080
user_nick: hhra
user_altnick: _hhra
user_ident: hhra
user_realname: Nosey Fucker
user_passhash: e75ea669d9b4e79f0538c2cd2c0f406bca4970f47a03538a47adbdf82e04e467#J?a5.D8tUPqtZDgT-Qyu
The final thing to do is to start znc and enable it starting automatically on boot. Ansible’s built-in modules support this natively in much the same way as they do on linux so its just a matter of adding
- name: start znc on boot
service: name=znc state=started enabled=yes
to the end of your playbook. Once done, you should be left with a complete playbook looking something like
- hosts: all
vars:
listen_port: 8080
user_nick: hhra
user_altnick: _hhra
user_ident: hhra
user_realname: Nosey Fucker
user_passhash: e75ea669d9b4e79f0538c2cd2c0f406bca4970f47a03538a47adbdf82e04e467#J?a5.D8tUPqtZDgT-Qyu
tasks:
- name: initialize ports db
command: portsnap fetch extract
args:
creates: /usr/ports
- name: update ports db
command: portsnap fetch update
- name: install znc
portinstall:
name: irc/znc
state: present
- stat: path=/usr/local/etc/znc/configs/znc.conf
register: config_file_stat
- template: src=znc.conf.tmpl dest=/usr/local/etc/znc/configs/znc.conf
when: not config_file_stat.stat.exists
- name: start znc on boot
service: name=znc state=started enabled=yes
which when run will isntall and initialize a copy of zsh ready for use. There’s so much more that could be done to further enhance this setup. Blog posts may follow about installing the lounge and a reverse-proxy on the server to provide nice access to both the znc web interface and an IRC client.