RStudio server ignores XDG_CONFIG_HOME

Dear developers,

I downloaded and installed RStudio Server v2022.12.0+353 for Ubuntu 22, following directions on RStudio Server - Posit However, I can't seem to get it to recognize the $XDG_CONFIG_HOME environmental variable, and all settings continue to be written to ~/.config/.

I set the variable using the standard export XDG_CONFIG_HOME=/full/path/ mechanism and run the server with sudo /usr/lib/rstudio-server/bin/rserver --server-daemonize=0. Similar questions on the forum seem to indicate that this should be sufficient, but I also tried writing the environmental variable to various .Renviron and .Renviron.site locations, all to no avail. What am I missing?

Happy to throw together a reproducible example, if helpful.

Reproducible example with Docker + Gitpod

  • Define the following Dockerfile:
FROM gitpod/workspace-base:2023-03-06-18-43-51

USER root

# Configuration for tzdata
ENV TZ=US/Eastern
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone

# Install R
RUN wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc |\
    tee -a /etc/apt/trusted.gpg.d/cran_ubuntu_key.asc && \
    add-apt-repository "deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/"
RUN apt-get update && apt-get install -y r-base gdebi-core

# Install RStudio
ARG RSTUDIO_VER="rstudio-server-2022.12.0-353-amd64.deb"
RUN wget "https://download2.rstudio.org/server/jammy/amd64/$RSTUDIO_VER" && \
    gdebi -n "$RSTUDIO_VER"

# Clean up
RUN rm -rf "$RSTUDIO_VER" && \
    rm -rf /var/lib/apt/lists/*

# Reset gitpod user credentials (for Rstudio login)
RUN echo "gitpod:gitpod" | chpasswd
USER gitpod
  • Build the container image with docker build -t rstudio:test .

  • Start a container from the above image:
    docker run -it --rm -p 8787:8787 -v "$PWD":/config -e XDG_CONFIG_HOME=/config rstudio:test

  • Inside the container, verify that XDG_CONFIG_HOME has been set:

gitpod ~ $ echo $XDG_CONFIG_HOME
/config
  • Launch the server with sudo /usr/lib/rstudio-server/bin/rserver, which will be served on port 8787. If requested to log in, use gitpod for both username and password.

  • Modify a global option, e.g., change the appearance theme.

  • Examine the location of saved options:

gitpod ~ $ ls -la /config
total 0
drwxr-xr-x 2 gitpod gitpod  6 Mar 15 12:03 .
drwxr-xr-x 1 root   root   65 Mar 15 12:14 ..

gitpod ~ $ ls ~/.config/rstudio/
dictionaries  rstudio-prefs.json

gitpod ~ $ cat ~/.config/rstudio/rstudio-prefs.json 
{
    "initial_working_directory": "~",
    "editor_theme": "Tomorrow Night 80s",
    "posix_terminal_shell": "bash"
}

Even though XDG_CONFIG_HOME is set to /config, the server continues to write settings to ~/.config.

It doesn't really matter what env vars rserver sees in this case; XDG_CONFIG_HOME is read by a separate process, rsession, and it reads the value only when that process starts up (not when it starts R, so you can't use .Renviron, etc).

So what I'd suggest as a first debugging step is to remove all the Renviron changes, start a new session, and run Sys.getenv("XDG_CONFIG_HOME") to confirm that the session is seeing the correct value.

Hi Jonathan,

I've never run the rsession process directly. Are there any flags to pass? For me, it fails with the following error message when I run it inside the container that I built in my previous post:

$ docker run -it --rm -p 8787:8787 -v "$PWD":/config -e XDG_CONFIG_HOME=/config rstudio:test

# Inside the container
gitpod ~ $ /usr/lib/rstudio-server/bin/rsession 
TTY detected. Printing informational message about logging configuration. Logging configuration loaded from '/etc/rstudio/logging.conf'. Logging to '/home/gitpod/.local/share/rstudio/log/rsession-.log'.
rsession-[34]: ERROR system error 2 (No such file or directory) [path: ]; OCCURRED AT rstudio::core::Error rstudio::r::session::discoverR(rstudio::r::session::RLocations*) src/cpp/r/session/RDiscovery.cpp:62; LOGGED FROM: int main(int, char* const*) src/cpp/session/SessionMain.cpp:2459

2023-03-16T19:44:38.133648Z [rsession-] ERROR system error 2 (No such file or directory) [path: ]; OCCURRED AT rstudio::core::Error rstudio::r::session::discoverR(rstudio::r::session::RLocations*) src/cpp/r/session/RDiscovery.cpp:62; LOGGED FROM: int main(int, char* const*) src/cpp/session/SessionMain.cpp:2459

Sorry, rsession is started by rserver and represents an R session in the browser. If you start your server and navigate to it in a browser, you are interacting with rsession. It's from your browser RStudio IDE session that you should run Sys.getenv("XDG_CONFIG_HOME"). Let me know what you see!

Ah. Thanks, Jonathan.

The rsession definitely does NOT see the environmental variable:

> Sys.getenv("XDG_CONFIG_HOME")
[1] ""

What's interesting is that the official rstudio container image doesn't have this problem. If I run it with

docker run -it --rm -p 8787:8787 -v "$PWD":/config -e XDG_CONFIG_HOME=/config rocker/rstudio

then the R session sees the environmental variable and the global options correctly appear in /config.

I am trying to understand how rocker/rstudio handles environmental variables, but there is an additional layer of complexity with the S6 server. I see that it copies the variables to ${R_HOME}/etc/Renviron.site on startup:

$ docker run --rm rocker/rstudio cat /etc/cont-init.d/01_set_env 

#!/usr/bin/with-contenv bash
# shellcheck shell=bash

## Set our dynamic variables in Renviron.site to be reflected by RStudio Server or Shiny Server
exclude_vars="HOME PASSWORD RSTUDIO_VERSION BATCH_USER_CREATION"
for file in /var/run/s6/container_environment/*; do
    sed -i "/^${file##*/}=/d" "${R_HOME}/etc/Renviron.site"
    regex="(^| )${file##*/}($| )"
    [[ ! $exclude_vars =~ $regex ]] && echo "${file##*/}=$(cat "${file}")" >>"${R_HOME}/etc/Renviron.site" || echo "skipping ${file}"
done

## only file-owner (root) should read container_environment files:
chmod 600 /var/run/s6/container_environment/*

If I do this manually in my container, the rsession sees those variables and writes dictionaries to /config, but the remaining options still get written to ~/.config/:

# On the host system
$ docker run -it --rm -p 8787:8787 -v "$PWD":/config -e XDG_CONFIG_HOME=/config rstudio:test

# Inside the container
gitpod ~ $ echo "XDG_CONFIG_HOME=$XDG_CONFIG_HOME" | sudo tee -a /etc/R/Renviron.site
gitpod ~ $ sudo /usr/lib/rstudio-server/bin/rserver

# Inside the rsession
> Sys.getenv("XDG_CONFIG_HOME")
[1] "/config"

# Changing appearance theme in Global Options...

# Back inside the container
gitpod ~ $ ls /config
R  rstudio

gitpod ~ $ ls /config/rstudio
dictionaries

gitpod ~ $ ls ~/.config/rstudio/
rstudio-prefs.json

gitpod ~ $ cat ~/.config/rstudio/rstudio-prefs.json 
{
    "initial_working_directory": "~",
    "editor_theme": "Solarized Dark",
    "posix_terminal_shell": "bash"
}

Do dictionaries and rstudio-prefs.json use different env variables, maybe?

They don't. As in the excellent Netflix series "Dark", It's not a question of "where" but "when". There's a lot of startup code that rsession runs before R itself is started. So setting XDG_CONFIG_HOME in Renviron is really too late; only code that runs after R boot will see the desired path.

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.