User Tools

Site Tools


2018:01:20:nic-ip-as-environment-variables

Setting NIC IP addresses as environment variables

Introduction

For me, most any work day consists of Ubuntu Server, Docker, Ansible, Python, and Golang; but not all server instances have Static IP addresses, some only have an Ephemeral IP address. When I need to pass an interface's address to systemd, shell script, Docker, Kubernetes, etc. without having to perform edits on code or configuration, this can become problematic.

An easy way to do so is with setup-network-environment via system initialization and optionally, VPN connection parameters (e.g. OpenVPN's up and down options). Running this program will produce (and subsequently update) an environment file (by default, located at /etc/network-environment) that can be parsed by Bash, systemd, and others, in order to populate variables.

An example of the generated environment file:

/etc/network-environment
LO_IPV4=127.0.0.1
ENO16777736_IPV4=192.168.12.10
DEFAULT_IPV4=192.168.12.10
TUN0_IPV4=172.16.12.10

Prerequisites

In this article, I'll assume that these prerequisites haven't been fulfilled (Snappy, Git, and Go aren't part of the standard install for Ubuntu Server 16 LTS), and will cover those installation processes as well.

Setup

Update the package cache:

sudo apt update

Set ~/.bashrc to be loaded by ~/.bash_profile: 1)

echo 'source $HOME/.bashrc' >> $HOME/.bash_profile

Snappy

Install Snappy:

sudo apt install -y snapd

Git

Install Git:

sudo apt install -y git

Golang

After you perform this step, please logout, and log back in. If you don't, Golang will not properly function for the next step.

Install the latest version of Golang:

snap install --classic go

The reason that I set $GOBIN to /usr/local/bin is because I want Go-based binaries to be accessible by the entire system. In a multi-user environment, your needs may differ, and plenty of people use $GOPATH/bin, and update $PATH, to reflect these utilities existing in their home directories.

That said, there's plenty of discussion on the Internet about what this should be set to 2) 3), so, YMMV.

Furthermore, the reason that I don't simply call source /etc/network-environment, is due to Bash not being able to parse variables with dashes in them (this seems to happen on particular Linux instances.)

Append environment variables to ~/.bashrc:

cat << 'EOF' | tee --append $HOME/.bashrc > /dev/null
# Golang
export GOPATH=$HOME/go
export GOBIN=/usr/local/bin
export PATH=$GOBIN:$PATH

# setup-network-environment
if [ -f /etc/network-environment ]; then
    tnef=`mktemp`
    cp -a /etc/network-environment ${tnef}
    sed --in-place 's~[^0-9A-Za-z\=\.\_/]\+~_~g' ${tnef}
    source ${tnef}
    export $(cut -d= -f1 ${tnef})
    rm -rf ${tnef}
fi
EOF

You remembered to logout and log back in, right? ;-)

setup-network-environment

Download, build, and install setup-network-environment:

go get github.com/kelseyhightower/setup-network-environment

Configure

systemd

Important shortcuts:

System:

  • Reload management parameters:
    systemctl daemon-reload

  • Enable specific service:
    systemctl enable NAME.service

  • Disable specific service:
    systemctl disable NAME.service

Service:

  • systemctl start NAME.service
  • systemctl restart NAME.service
  • systemctl stop NAME.service
  • Overview:
    systemctl status NAME.service

  • Log:
    journalctl --follow --unit=NAME.service

List:

  • Start when system boots:
    systemctl list-unit-files --state=enabled

  • Currently Running:
    systemctl list-units --type=service --state=running

  • Active (running or exited):
    systemctl list-units --type=service --state=active

2018/01/28 19:25 · Louis T. Getterman IV

Service

  1. Save:
    wget \
        --output-document=/etc/systemd/system/setup-network-environment.service \
        https://thad.getterman.org/_export/code/2018/01/20/nic-ip-as-environment-variables?codeblock=9
  2. Set permissions: chmod -v 644 /etc/systemd/system/setup-network-environment.service
  3. Reload management parameters: systemctl daemon-reload
  4. Enable service: systemctl enable setup-network-environment.service
  5. Start service: systemctl start setup-network-environment.service
  6. Check status: systemctl status setup-network-environment.service
  7. View generated environment file: cat /etc/network-environment
/etc/systemd/system/setup-network-environment.service
[Unit]
Description=Setup Network Environment
Documentation=https://github.com/kelseyhightower/setup-network-environment
Requires=network.target
After=network.target

[Service]
ExecStart=/usr/local/bin/setup-network-environment
RemainAfterExit=yes
Type=oneshot

[Install]
WantedBy=multi-user.target

Dependencies

This is an optional step, and to serve as an example for using systemd to assign Nginx to the host's default IPv4 address with environment variables.

  1. Save to:
    wget \
        --output-document=/etc/systemd/system/docker-nginx.service \
        https://thad.getterman.org/_export/code/2018/01/20/nic-ip-as-environment-variables?codeblock=11
  2. Set permissions: chmod -v 644 /etc/systemd/system/docker-nginx.service
  3. Reload management parameters: systemctl daemon-reload
  4. Start service: systemctl start docker-nginx.service
  5. Check status: systemctl status docker-nginx.service
  6. View the default Nginx page: curl "http://${DEFAULT_IPV4}"
  7. Stop service: systemctl stop docker-nginx.service
  8. Remove test service: rm -rfv /etc/systemd/system/docker-nginx.service
  9. Reload management parameters: systemctl daemon-reload
/etc/systemd/system/docker-nginx.service
[Unit]
Description=Docker Nginx example.
Requires=docker.service setup-network-environment.service
After=docker.service setup-network-environment.service

[Service]
EnvironmentFile=/etc/network-environment
TimeoutStartSec=0
Restart=always
ExecStartPre=-/usr/bin/docker stop %n
ExecStartPre=-/usr/bin/docker rm %n
ExecStartPre=/usr/bin/docker pull nginx
ExecStart=/usr/bin/docker run \
    --rm \
    --name=%n \
    --publish ${DEFAULT_IPV4}:80:80 \
    nginx

[Install]
WantedBy=multi-user.target

OpenVPN (optional)

In (each of) your OpenVPN configuration file(s) that are usually located in /etc/openvpn/, add 2 entries:

up /usr/local/bin/setup-network-environment
down /usr/local/bin/setup-network-environment

Conclusion

You are now able to use variables that represent the IP address of each of your system's NICs. As you see with the Dependencies example in this article, you can quickly bind a service to an interface's address, regardless of its IP address state as static or dynamic.

To expand upon real-world use cases of this example: when I want a containerized service to bind to VPN connections, I use ${TUN0_IPV4} in place of the ${DEFAULT_IPV4} parameter.

See also

References

External links

2018/01/20/nic-ip-as-environment-variables.txt · Last modified: 2018/01/31 01:00 by Louis T. Getterman IV