Use variables with profiles?

I have a profile which maps config files from host to containier. Can I write the profile in a way that the path key has a user’s home in it which I designate for the particular container? Or do I have to to copy this profile and change just the path (the /home/{{user}}/...user part) for each one? That would be pretty sad. Or is there some solution to this? Some UID-based approach would be great as well, translate UID 1000 for the home directory in each container.

There a lot of ways to customize an instance or a system. You can easily set and change, for example, a profile configuration e.g. with a bash script, and you can either then create a default profile for a separate project or create a custom profile within the current project that can have user-specific features, for example.

incus profile create $Username
incus profile show default | incus profile edit $Username
incus profile set $Username <parameter>
# e.g. set a custom network called $UserNetwork for the user
# incus profile device set $Username eth0 network=$UserNetwork
# Or set storage pool (different dataset, different pool - whatever)
# incus profile device set $Username root pool=$UserStorage 
# There's a lot you can do here.

Of course, if you want to customize an instance, you also have cloud-init which can configure a lot of things that are machine and/or user specific.

Not sure if this is helpful?

Andrew

I want something like this that can be applied to any of my containers:

...
devices:
  microconfig:
    path: /home/{{user with UID 1000}}/.config/micro/bindings.json
    shift: "true"
    source: /home/dhost/.config/micro/bindings.json
    type: disk
...

One profile and one path that works for all containers that mostly have different usernames.
Or map this file to all directories under /home/... that could work too.
Otherwise I need different profiles for each container :frowning:.
Some scriptability or variable/command substitution within incus profiles is what I am lacking here.

TL;DR: no…

Long answer:
Unfortunately, this is not possible. There have been several discussions about templating, but it’s a very hard question: what fields can be templated? how readable will the final configuration be for people?
There will be a bit of work to further allow people to dynamically edit the QEMU configuration for VMs this month, but it is out of scope for containers.
Your question feels even harder, because you’re not only asking Incus to configure mounts depending on files within the container (e.g. /etc/passwd) before said container is even started, but also to have a templating engine able to interact with these files. While I still think we should add templating to Incus, what you’re asking feels like a considerably greater effort!

Something simpler in terms of implementation would be:

incus variable set mycontainer home /home/user

This profile then could be applied to all containers that have home variable set:

...
devices:
  microconfig:
    path: "{{home}}/.config/micro/bindings.json"
    shift: "true"
    source: /home/dhost/.config/micro/bindings.json
    type: disk

Variable support for profiles should be opt-in, so no worry about backwards compatibility. Would work flawlessly.

But I get it that there are other priorities.

Sure, that could work. I think we’d rather use the user.* configuration keys (e.g. user.homedir: "/home/user"), but they are not yet plugged into any kind of templating engine. From what I understood from @stgraber, device configuration needs to be queried quite often, and fast, and having a templating engine run on top may be too computationally intensive.
Still, I think we should look into it…

1 Like

As a workaround, you can push config files to the container like this (change <instance_name>):

incus file push -p -r /home/dhost/.config/micro/ <instance_name>$( incus exec <instance_name> -- getent passwd 1000 | cut -d: -f6 )/.config/micro/

Of course, it’s not as convenient as having a map in a profile.

Another option would be to have the disk device set at a common path, maybe somewhere under /var/lib or something, then have cloud-init copy that data or set up a symlink following user creation. Basically letting the container itself figure out what the correct uid and homedir is.

symlink + cloud-init would probably work but is wonkier and restricts me to cloud-init images.
It would be lovely if profiles could be parameterized as illustrated above. They could be more reusable, more flexible. I have other use cases that would benefit from it too and from what I’ve heard others users do too.
In my opinion it would be sweet if instead of having to hard-code container specific paths, group ids, whatever into profiles, these values could be partially set per container and then resolved in a generic fashion.

Again as a workaround, for these cases where you can’t use cloud-init, you can push a little script to the container that will do the symlinking / copying from the shared storage.

Yes, oviously, but best would be if profiles had this flexibility.