Skip to content
35 changes: 35 additions & 0 deletions workbench/template/Containerfile.ubuntu2204.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,25 @@ ENV PWB_DIAGNOSTIC_DIR=/var/log/rstudio
ENV PWB_DIAGNOSTIC_ENABLE=false
ENV PWB_EXIT_AFTER_VERIFY=false

{% if Image.IsDevelopmentVersion %}
### Pre-create rstudio-server user so deb postinst finds it and UID/GID stays 999 across image rebuilds ###
# Idempotent so a cached layer (or the deb postinst) that already created the
# account does not fail the build.
RUN if ! getent group rstudio-server >/dev/null; then \
groupadd --system --gid 999 rstudio-server; \
fi \
&& if ! getent passwd rstudio-server >/dev/null; then \
useradd --system --uid 999 --gid rstudio-server \
--no-create-home --home-dir /var/lib/rstudio-server \
--shell /usr/sbin/nologin \
rstudio-server; \
fi \
&& if [ "$(id -u rstudio-server)" != 999 ] || [ "$(id -g rstudio-server)" != 999 ]; then \
echo "ERROR: rstudio-server must be uid/gid 999, got uid=$(id -u rstudio-server) gid=$(id -g rstudio-server)" >&2; \
exit 1; \
fi

{% endif %}
### Setup environment ###
{{ apt.run_setup() }}

Expand Down Expand Up @@ -94,7 +113,23 @@ COPY "{{ Path.Version }}/conf/jupyter/*" "{{ Path.Version }}/conf/launcher/*" "{

### Configure Workbench ###
RUN mkdir -p /var/lib/rstudio-server/monitor/log \
{% if Image.IsDevelopmentVersion %}
/var/lib/rstudio-server/conf \
/var/lib/rstudio-server/body \
/var/lib/rstudio-server/proxy \
/var/lib/rstudio-launcher \
/var/log/rstudio \
/var/run/supervisor \
&& chown -R rstudio-server:rstudio-server \
/var/lib/rstudio-server \
/var/lib/rstudio-launcher \
/var/log/rstudio \
/var/run/supervisor \
&& chmod -R g+w /var/lib/rstudio-server /var/lib/rstudio-launcher /var/log/rstudio /var/run/supervisor \
&& find /var/lib/rstudio-server /var/lib/rstudio-launcher /var/log/rstudio /var/run/supervisor -type d -exec chmod g+s {} + \
{% else %}
&& chown -R rstudio-server:rstudio-server /var/lib/rstudio-server/monitor \
{% endif %}
&& mkdir -p /startup/custom/ \
&& mkdir -p /startup/user-provisioning/ \
&& printf '\n# allow home directory creation\nsession required pam_mkhomedir.so skel=/etc/skel umask=0077\n' >> /etc/pam.d/common-session \
Expand Down
35 changes: 35 additions & 0 deletions workbench/template/Containerfile.ubuntu2404.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,25 @@ ENV PWB_DIAGNOSTIC_DIR=/var/log/rstudio
ENV PWB_DIAGNOSTIC_ENABLE=false
ENV PWB_EXIT_AFTER_VERIFY=false

{% if Image.IsDevelopmentVersion %}
### Pre-create rstudio-server user so deb postinst finds it and UID/GID stays 999 across image rebuilds ###
# Idempotent so a cached layer (or the deb postinst) that already created the
# account does not fail the build.
RUN if ! getent group rstudio-server >/dev/null; then \
groupadd --system --gid 999 rstudio-server; \
fi \
&& if ! getent passwd rstudio-server >/dev/null; then \
useradd --system --uid 999 --gid rstudio-server \
--no-create-home --home-dir /var/lib/rstudio-server \
--shell /usr/sbin/nologin \
rstudio-server; \
fi \
&& if [ "$(id -u rstudio-server)" != 999 ] || [ "$(id -g rstudio-server)" != 999 ]; then \
echo "ERROR: rstudio-server must be uid/gid 999, got uid=$(id -u rstudio-server) gid=$(id -g rstudio-server)" >&2; \
exit 1; \
fi

{% endif %}
### Setup environment ###
{{ apt.run_setup() }}

Expand Down Expand Up @@ -94,7 +113,23 @@ COPY "{{ Path.Version }}/conf/jupyter/*" "{{ Path.Version }}/conf/launcher/*" "{

### Configure Workbench ###
RUN mkdir -p /var/lib/rstudio-server/monitor/log \
{% if Image.IsDevelopmentVersion %}
/var/lib/rstudio-server/conf \
/var/lib/rstudio-server/body \
/var/lib/rstudio-server/proxy \
/var/lib/rstudio-launcher \
/var/log/rstudio \
/var/run/supervisor \
&& chown -R rstudio-server:rstudio-server \
/var/lib/rstudio-server \
/var/lib/rstudio-launcher \
/var/log/rstudio \
/var/run/supervisor \
&& chmod -R g+w /var/lib/rstudio-server /var/lib/rstudio-launcher /var/log/rstudio /var/run/supervisor \
&& find /var/lib/rstudio-server /var/lib/rstudio-launcher /var/log/rstudio /var/run/supervisor -type d -exec chmod g+s {} + \
{% else %}
&& chown -R rstudio-server:rstudio-server /var/lib/rstudio-server/monitor \
{% endif %}
&& mkdir -p /startup/custom/ \
&& mkdir -p /startup/user-provisioning/ \
&& printf '\n# allow home directory creation\nsession required pam_mkhomedir.so skel=/etc/skel umask=0077\n' >> /etc/pam.d/common-session \
Expand Down
15 changes: 12 additions & 3 deletions workbench/template/startup/supervisord.conf.jinja2
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
; supervisor config file
{%- if Image.IsDevelopmentVersion %}
{%- set supervisor_socket = "/var/run/supervisor/supervisor.sock" %}
{%- set supervisor_pidfile = "/var/run/supervisor/supervisord.pid" %}
{%- else %}
{%- set supervisor_socket = "/var/run/supervisor.sock" %}
{%- set supervisor_pidfile = "/var/run/supervisord.pid" %}
{%- endif %}

[unix_http_server]
file=/var/run/supervisor.sock ; (the path to the socket file)
file={{ supervisor_socket }} ; (the path to the socket file)
chmod=0700 ; sockef file mode (default 0700)

[supervisord]
logfile=/dev/stdout ; (main log file;default $CWD/supervisord.log)
{%- if not Image.IsDevelopmentVersion %}
user=root
pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
{%- endif %}
pidfile={{ supervisor_pidfile }} ; (supervisord pidfile;default supervisord.pid)
; should configure each program to use stdout/stderr
; childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP)
logfile_maxbytes=0
Expand All @@ -22,7 +31,7 @@ nodaemon=true
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock ; use a unix:// URL for a unix socket
serverurl=unix://{{ supervisor_socket }} ; use a unix:// URL for a unix socket

; The [include] section can just contain the "files" setting. This
; setting can list multiple files (separated by whitespace or
Expand Down
49 changes: 46 additions & 3 deletions workbench/template/test/goss.yaml.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ user:
rstudio-server:
exists: true
uid: 999
gid: {% raw %}{{ if and (eq .Env.IMAGE_VARIANT "Standard") (and (eq .Env.IMAGE_OS_NAME "ubuntu") (eq .Env.IMAGE_OS_VERSION "24.04")) }}997{{ else }}999{{ end }}{% endraw %}
gid: {% if Image.IsDevelopmentVersion %}999{% else %}{% raw %}{{ if and (eq .Env.IMAGE_VARIANT "Standard") (and (eq .Env.IMAGE_OS_NAME "ubuntu") (eq .Env.IMAGE_OS_VERSION "24.04")) }}997{{ else }}999{{ end }}{% endraw %}{% endif %}
groups:
- rstudio-server

group:
rstudio-server:
exists: true
gid: {% raw %}{{ if and (eq .Env.IMAGE_VARIANT "Standard") (and (eq .Env.IMAGE_OS_NAME "ubuntu") (eq .Env.IMAGE_OS_VERSION "24.04")) }}997{{ else }}999{{ end }}{% endraw %}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reverts difference in gid between Ubuntu 22 and 24. I recall we ran into something with this, but don't remember the specifics of why or what it was. d8b1ced

It could just be that the packages installed before took the higher gid before the rstudio-server user/group was created.

Copy link
Copy Markdown
Contributor

@bschwedler bschwedler May 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In workbench:2026.05.0-ubuntu-24.04

  users:100              ← base ubuntu:24.04
  messagebus:101         ← from dbus (Standard pkgs pull it in)
  sssd:102               ← from sssd (Standard-only)
  rstudio-server:997     ← workbench install
  systemd-network:998    ← from libnss-systemd/systemd-resolved (Standard pkgs)
  systemd-journal:999    ← from systemd (Standard pkgs)
  ubuntu:1000            ← base ubuntu:24.04

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So it looks like the cause is the installation of sssd, which in turn pulls in dbus and libnss-systemd

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. So this is related to the helm changes we're working on to run as a service account.

In there you want a stable UUID and GID because it is what you set the workbench pod to run as. I can take a look at the failure - I think it would be better if this was stable between workbench versions.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. I understand the motivation now. In that case, I would like us to try to apply this to all existing versions of the images so that they work with the helm chart out of the box.

@ianpittwood What do you think?

gid: {% if Image.IsDevelopmentVersion %}999{% else %}{% raw %}{{ if and (eq .Env.IMAGE_VARIANT "Standard") (and (eq .Env.IMAGE_OS_NAME "ubuntu") (eq .Env.IMAGE_OS_VERSION "24.04")) }}997{{ else }}999{{ end }}{% endraw %}{% endif %}

package:
rstudio-server:
Expand Down Expand Up @@ -82,11 +82,54 @@ file:
# Check for rstudio-launcher executable
/usr/lib/rstudio-server/bin/rstudio-launcher:
exists: true
{%- if Image.IsDevelopmentVersion %}
# Check for rstudio-server runtime directories with correct ownership and setgid
/var/lib/rstudio-server:
exists: true
owner: rstudio-server
group: rstudio-server
mode: "2775"
/var/lib/rstudio-server/monitor/log:
exists: true
owner: rstudio-server
group: rstudio-server
/var/lib/rstudio-server/conf:
exists: true
owner: rstudio-server
group: rstudio-server
/var/lib/rstudio-server/body:
exists: true
owner: rstudio-server
group: rstudio-server
/var/lib/rstudio-server/proxy:
exists: true
owner: rstudio-server
group: rstudio-server
# rstudio-launcher resets its scratch directory to 0755 on startup, so we
# only assert ownership here; the build-time setgid mode does not survive.
/var/lib/rstudio-launcher:
exists: true
owner: rstudio-server
group: rstudio-server
/var/log/rstudio:
exists: true
owner: rstudio-server
group: rstudio-server
mode: "2775"
/var/run/rstudio-server:
exists: true
/var/run/supervisor:
exists: true
owner: rstudio-server
group: rstudio-server
mode: "2775"
{%- else %}
# Check for rstudio-server monitor log directory
/var/lib/rstudio-server/monitor/log:
exists: true
owner: rstudio-server
group: rstudio-server
{%- endif %}
# Check for code-server executable (path varies based on RStudio Workbench version)
{{ '{{ $version_split := split "." "' | safe }}{{ Image.Version }}{{ '" }}' | safe }}
{% raw -%}
Expand Down Expand Up @@ -186,7 +229,7 @@ file:

command:
"Ensure rstudio-server has permissions to log directory":
exec: su rstudio-server -c 'touch /var/lib/rstudio-server/monitor/log/rstudio-server.log'
exec: {% if Image.IsDevelopmentVersion %}sudo -u rstudio-server touch /var/lib/rstudio-server/monitor/log/rstudio-server.log{% else %}su rstudio-server -c 'touch /var/lib/rstudio-server/monitor/log/rstudio-server.log'{% endif %}
exit-status: 0
"Ensure server log can be created":
exec: touch /var/log/rstudio-server.log
Expand Down
Loading