Ssh into an alpine container, user nobody, root

Hi there,

I am running a docker container, based on alpine:3.13.3, with:

USER nobody:nobody

When I use the html shell, I have:

/app $ getent passwd $(whoami)
nobody:x:65534:65534:nobody:/:/sbin/nologin

But I can not ssh to this container, following the doc Connecting with SSH | Render · Cloud Hosting for Developers, tail is

debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: pledge: filesystem full
debug1: channel 0: free: client-session, nchannels 1
Connection to ssh.frankfurt.render.com closed by remote host.
Connection to ssh.frankfurt.render.com closed.
Transferred: sent 2760, received 1464 bytes, in 15.7 seconds
Bytes per second: sent 175.8, received 93.2
debug1: Exit status -1

When I use root user in ssh command, then I have Permission denied (publickey).

Did anyone succeeded in ssh’ing into an alpine container?
With what user?

Cheers, Thierry

1 Like

Hi Thierry,

For Docker services, SSH needs to be able to set up permissions correctly. It’s trying to write to ~/.ssh, which for your user is /.ssh (note the 6th part of the passwd entry, where the user’s home directory is /). You can modify your Docker container to support this by changing:

USER nobody:nobody

to:

RUN mkdir /.ssh
RUN chown nobody:nobody /.ssh
USER nobody:nobody

Additionally, your container has configured the nobody user to not support logging in (and therefore SSH), which is what the last part of the passwd entry is communicating with /sbin/nologin. You can change this by adding sed -ri 's/^(nobody.*:)\/sbin\/nologin$/\1\/bin\/sh/' /etc/passwd in your Dockerfile before switching users. Putting it all together, you have:

RUN mkdir /.ssh
RUN chown nobody:nobody /.ssh
RUN sed -ri 's/^(nobody.*:)\/sbin\/nologin$/\1\/bin\/sh/' /etc/passwd
USER nobody:nobody

That should let you log in with SSH :slight_smile:

1 Like

Hello render,
thanks for the help!

What did not work : hack nobody + ENV HOME

I changed my dockerfile as suggested, below I print more for context:

WORKDIR /app

# Here, the change proposed:
# https://community.render.com/t/ssh-into-an-alpine-container-user-nobody-root/3335/2
RUN chown nobody:nobody /app \
    && mkdir /.ssh \
    && chown nobody:nobody /.ssh \
    && sed -ri 's/^(nobody.*:)\/sbin\/nologin$/\1\/bin\/sh/' /etc/passwd

USER nobody:nobody

# COPY --from=build --chown=nobody:nobody /stuff ./

ENV HOME=/app
ADD start.sh ./

CMD ["./start.sh"]

But I could not ssh in container

debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: pledge: filesystem full
debug1: channel 0: free: client-session, nchannels 1
Connection to ssh.frankfurt.render.com closed by remote host.
Connection to ssh.frankfurt.render.com closed.
Transferred: sent 2760, received 1464 bytes, in 15.5 seconds
Bytes per second: sent 178.2, received 94.5
debug1: Exit status -1

I think a cause may have been the ENV HOME statement?
It happens ~nobody/.ssh is empty:

/app $ cd ~nobody/.ssh
/.ssh $ ls -laF 
total 8
drwxr-sr-x    2 nobody   nobody        4096 Feb  4 10:03 ./
drwxr-xr-x    1 root     root          4096 Feb  4 10:21 ../

But ~/.ssh is not:

/app $ echo $HOME
/app
/app $ cat ~/.ssh/authorized_principals
render

What worked, dedicated user

With user home as /app (ugly but conservative).

RUN adduser -D -g $user -h /app -s /bin/sh $user

USER $user:$user

WORKDIR /app
# COPY --from=build --chown=nobody:nobody /stuff ./

Here is an output of connection

Authenticated to ssh.frankfurt.render.com ([35.158.59.44]:22) using "publickey".
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: pledge: filesystem full
debug1: Sending environment.
debug1: channel 0: setting env LANG = "en_US.UTF-8"
debug1: channel 0: setting env LC_ALL = "en_US.UTF-8"
Welcome to Alpine!

Cheers!