Installing HA in docker on Ubuntu as non-root user

I’d previously started a discussion on reddit, but wanted to complete it here.

My goal was to run HA (not hass.io) in docker on a Ubuntu 16.04 VM as non-root. I’m not sure whether this is correct (would appreciate feedback), however I do seem to have it working with the following steps:

myUser@UbutntuTHAW:~$ sudo adduser --system homeassistant
myUser@UbutntuTHAW:~$ sudo addgroup homeassistant
myUser@UbutntuTHAW:~$ sudo mkdir /etc/homeassistant
myUser@UbutntuTHAW:~$ sudo chown homeassistant:homeassistant /etc/homeassistant/
myUser@UbutntuTHAW:~$ docker run -d -u 112:1001 --restart unless-stopped --name="hass" -v /etc/homeassistant:/config -v /etc/localtime:/etc/localtime:ro --net=host homeassistant/home-assistant

The end result of this is that all of the config files auto-generated in /etc/homeassistant are created with user:group homeassistant:homeassistant.

That will work fine, but there is no need to create a separate homeassistant user in the host. The necessary security is already created by running HA in a docker container.

Given some of the exploits that are being found (Pwn2Own) I feel safer running anything possible as non-root. Especially something like HA that will be (partly) exposed to the Internet.

Except that everything Docker runs as root anyway.

Warning: The docker group grants privileges equivalent to the root user. For details on how this impacts security in your system, see Docker Daemon Attack Surface.

It would make some things easier if HA in Docker followed (something like) the linuxserver.io pattern of using a PUID/GUID evn variable: https://www.linuxserver.io/docs/puid-pgid

The main issue I run in to right now is that I sometimes want to access config files that HA creates, and by default those files are owned by root (because this is how the app is run in docker). I can change the files to be owned by a different user/group and HA will continue to work with the files fine (because, as discussed it does run as root) - but it would be nice if I didn’t have to.

8 Likes

Exactly the issue I’ve got which led me to this post.

I have to manually change the ownership of the my HA config files from root:root to the same UID/GID that is used in my other containers. Using Syncthing highlighted the issue because it didn’t have permissions to write to the HA config folder.

Could the Docker image of HA be updated to accept custom PUID and PGID environment variables please?

4 Likes

It looks like a solution to my issue described above is to use sticky bits on the home assistant folder managed by the host, using chmod g+s dir

Create a test file from within the container before setting the sticky bit:

$ docker exec -it homeassistant /bin/bash
root@hass:/usr/src/app# cd /config/
root@hass:/config# touch test
root@hass:/config# ls -al
...
-rw-rw-r--+  1 root root        0 Oct 29 20:06 test

This defaults to root:root. Exit the container and set the sticky bit on your home assistant folder:

$ chmod g+s ~/docker/homeassistant

Return to the container and create another test file

$ docker exec -it homeassistant /bin/bash
root@hass:/usr/src/app# cd /config/
root@hass:/config# touch test2
root@hass:/config# ls -al
...
-rw-rw-r--+  1 root root        0 Oct 29 20:06 test
-rw-rw-r--+  1 root  999        0 Oct 29 20:08 test2

Success! Works on directories created within the container too. :slight_smile:

Interesting - has this caused any other problems since you started using it?

I have a similar setup like that, but my docker environment in on ubuntu 18.84 server. What I did tough is, I added a second drive to my system and changed the ownership to the host username instead of root. I also made the host user a member of the docker group. So far everything worked with no issue.

…which does nothing since all the processes inside container are run as “root”.
You can check by going inside container:

docker exec -it <container name> bash
ps -aef

All the files are owned by 1010, but ran by root.
That’s a no-go.

Also it would be great to have some official “Paranoid configuration Guide”, since there is not much info on that topic:

  • What are the implications of running with --net=host
  • How to close Docker Server Port from accessing from non-localhost
  • How to jail Home-assistant user from leaving configuration folder

and so on.

1 Like

I did this as well but the umask inside the container is 0022 which means that group perms are r-- how did you get your umask set to allow writing by group?

Not sure - I see that my umask is 0022 as well, but if I create a file within the container, it’s set read/writable (-rw-rw-r–)

I migrated my python venv install to docker and finally got non-root working. Here is what worked for me:

On my host, I already had a dedicated user for homeassistant called…homeassistant.

  1. I created an empty config directory on host with this user. THIS WAS THE CRITICAL STEP because otherwise the config directory would be created as root, then the container would stop because lack of permission.
  2. I am not using docker-compose (at least not yet), therefore, I run docker run with the --user option value as uid:gid for my host user, such as:
docker run --user 999:999 --init -d --name="homeassistant" -v /home/homeassistant/.homeassistant:/config -v /etc/localtime:/etc/localtime:ro --net=host homeassistant/odroid-xu-homeassistant

Your uid / gid: id -u / id -g
I had to specify using numbers unless I shared /etc/passwd with container, which I’d rather not do.

You can see the processes are run appropriately:

bash-4.4$ ps aux
PID   USER     TIME  COMMAND
    1 999       0:00 /dev/init -- /bin/entry.sh python3 -m homeassistant --config /config
    6 999       0:17 /usr/local/bin/python3 -m homeassistant --config /config

Hey @ralfaro
I keep pulling my hair out with docker and UID/GID, I only am having this problem with Home-Assistant containers, all my others work just fine. I always seem to struggle with permissions in Linux in general so no doubt it is something stupid that I am doing, but wish there was a PUID/PGID as linuxserver for env. variables to make life easier.

How on earth are you getting this to work? I’ve tried all sorts of tricks and keep getting the following errors:

Unable to find configuration. Creating default one in /config,
Unable to create default configuration file /config/configuration.yaml,
Error getting configuration path,
Error doing job: Unclosed client session,
Error doing job: Unclosed connector,

Then the container quits.

Docker run looks as follows:

docker run --user 999:999 --init -d --name="home-assistant" -v /data/Docker/home-assistant:/config -v /etc/localtime:/etc/localtime:ro -v /mnt/nfs/Certs:/ssl:ro --net=LAN1 homeassistant/home-assistant

Directory ownership and permissions:

drwxrwxr-x 5        999 docker 4096 May 21 10:32 home-assistant

Short of building my own dockerfile I am at a loss here, any words of wisdom would be much appreciated :slight_smile:

May be you should crate a user docker with uid=999

Do you have a user on your host with id 999? Looks like it may be mapped to docker.

Did you create the config directory first with your host user, then run docker run command? I found this to be a critical step or else the user/group would be root or docker user (I wanted my homeassistant user to be used – this is the user with 999 on my machine)

I did have a user created with 999 to just test (ive changed it back now). I am actually using user id 1039 (which is my user on my host).

Is home assistant expecting to be run as docker?

But even if I run with

--user 1039:999

I still get the same errors as in my previous post.
What permissions should my user have?

Did you create the host directory with host user before running docker run ?

Thanks for the follow up @ralfaro

Yep created it as I always do, from my host user. I use the exact same process as defined by you guys above on all of my other containers. However Home Assistant just refuses to deploy properly haha.

Just for sanity and to write out my setup/approach in black and white to see if its something stupid that I am doing.

I have setup my UID’s and GID’s as per my synology NAS because it wont let me define the UID and GID and its assigned by itself. So for ease of file shares/NFS etc. I created a dockeruser and assigned that user to group users.

dockeruser UID = 1039
group user GID = 100

I have then replicated all of this on my ubuntu server nuc-docker02 host.

Assigned dockeruser permissions to docker so that user can deploy containers etc.

All of my docker mount directories reside in /data/Docker and that is the dockeruser Home directory:

adduser --uid 1039 -gid 100 --home /data/Docker dockeruser
>
ls -l /data
drwxr-xr-x 13 dockeruser users 4096 May 21 13:48 Docker

The /data/Docker/home-assistant directory is then created by dockeruser. Obviously my above examples are just me trying different things and simplifying everything back down, which still fails.

Below is a list of two users and what groups they belong to, my main user and dockeruser, I have even added dockeruser to sudo group just to see if that would do it! Clutching at straws there lol.

nickcj@nuc-docker02:~$ id
uid=1000(nickcj) gid=1000(nickcj) groups=1000(nickcj),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd),999(docker)
nickcj@nuc-docker02:~$ id dockeruser
uid=1039(dockeruser) gid=100(users) groups=100(users),27(sudo),999(docker)

I have tried also to deploy this from my main user nickcj who’s home directory is standard /home/nickcj and using UID=1000 and GID=1000

I have also tried bind mounting /etc/passwd:/etc/passwd:ro to see if the issue is due to the fact that those users don’t exist in the container so causing issues that way…nothing!

Any ideas, really would be welcomed :smile: