Create new user with home dir in a volume

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!