Create new user with home dir in a volume

Howdy!

I am attempting to set up a git user on my app in order to use a git server, saving the git repos to a volume.

I think I am currently facing the problem of not knowing how to give the git user permission to write to it’s home directory, as the volume is not mounted when the docker image is being built.

Any tips? In the end, I want to be able to do git remote add origin git@my-app.fly.dev:some/repo.git and git push origin main and have it push up to the volume.

I also want the git user to be able to (in my Elixir/Phoenix app) do bin/my-app rpc "some stuff", so i’m not sure if there are other things i need to do to make the git user able to do that, as that seems to be owned by the nobody user in the default setup.

I also will need my Elixir app to be able to touch files in the git users home directory. If it is easier to actually just have a single git user that does everything, that is also an option I think.

Thanks!

Okay, I was able to get it all working, not entirely sure on if it’s the best way or any implications however. This is for a silly couple day project so I don’t think it will affect me very much, but if you know of a better way so other’s with more production use cases come by they can know of other avenues.

Note: I am modifying the Dockerfile that Fly creates for you when you deploy a basic Phoenix project.

I use ubuntu as the release image instead of debian, this is how I was able to install the latest version of git.

ARG ELIXIR_VERSION=1.14.2
ARG OTP_VERSION=25.1.2
ARG DEBIAN_VERSION=jammy-20220428

ARG BUILDER_IMAGE="hexpm/elixir:${ELIXIR_VERSION}-erlang-${OTP_VERSION}-ubuntu-${DEBIAN_VERSION}"
ARG RUNNER_IMAGE="ubuntu:${DEBIAN_VERSION}"

Then

  • I make sure that openssh-server is installed
  • add a git user
  • write the port override to the sshd_config
  • use git as the user instead of nobody (not sure the implications of this)
  • start the server
FROM ${RUNNER_IMAGE}

RUN apt-get update -y && apt-get install -y software-properties-common gpg && add-apt-repository ppa:git-core/ppa && apt-get update -y && apt-get install -y libstdc++6 openssl libncurses5 locales git openssh-server vim \
  && apt-get clean && rm -f /var/lib/apt/lists/*_*

# Set the locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen && locale-gen

ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8

RUN useradd -U git

RUN echo "Port 2022" > /etc/ssh/sshd_config.d/git.conf

WORKDIR "/app"
RUN chown git /app

# set runner ENV
ENV MIX_ENV="prod"

# Only copy the final release from the build stage
COPY --from=builder --chown=git:root /app/_build/${MIX_ENV}/rel/twit ./

CMD ["/app/bin/server"]
# Appended by flyctl
ENV ECTO_IPV6 true
ENV ERL_AFLAGS "-proto_dist inet6_tcp"

Then I also modify the script overlay that is generate that actually invokes the mix release

  • start the ssh service
  • change the ownership of the mounted volume at /home/git. this basically uses the volume as the git users home dir
  • switch to the git user
  • echo the authorized keys into the git users ssh config (these are stored as a fly secret right now)
  • start the server as the git user (for something it wasn’t starting it as the git user before so i added this and then it worked, not sure if i missed something though, so i left it as is).
#!/bin/sh

service ssh start

chown git /home/git

su - git

mkdir -p ~/.ssh
echo "$KEYS" > ~/.ssh/authorized_keys

cd -P -- "$(dirname -- "$0")"
su -c 'PHX_SERVER=true exec ./twit start' git

Now, with all of that, I have the following in my fly.toml for forwarding the correct ports. The alternative port is required because Fly takes control of port 22 to enable fly ssh console.

[[services]]
  internal_port = 2022
  protocol = "tcp"

  [[services.ports]]
    port = 2022

Now, I have my user (currently… me :sweat_smile:) add this to their own SSH config. This tells their ssh client to use port 2022 instead.

Host *fly.dev
  Hostname myflydomain.fly.dev
  Port 2022

Finally, I can do (assuming you have created a bare git repo at /home/git/mhanberg/somerepo.git on your volume.

$ git remote add origin git@myflydomain.fly.dev:mhanberg/somerepo.git
$ git push origin main

And voila! :tada:

So, if anyone more knowledgeable in linux/ops things sees anything overtly wrong with this approach, please let me know!