Run content as the current user

Enhanced Advanced

This guide walks through configuring Posit Connect so that interactive content runs as the current user: under the Unix account of the person viewing it, rather than under a single shared service account.

The main reason to run content as the current user is to control access to data on a shared filesystem. Because each process runs under the viewer’s own Unix account, it reads and writes files as that person, so you can govern which data each user can access with standard Unix filesystem permissions. Connect supports current user execution for interactive applications, such as Shiny and Streamlit apps, and for APIs, such as Plumber, Flask, FastAPI, and Node.js. It is not available for static content.

Background

By default, Connect runs all content under a single shared Unix account (rstudio-connect). Every process reads and writes files as that one account, so on a shared filesystem all content has the same access to data, no matter who is viewing it. This is the recommended configuration for most installations.

Current user execution changes this. When a user opens an interactive application, Connect launches the process under the Unix account associated with that user. The application then reads and writes files as that specific person, so you can use standard Unix filesystem permissions, such as user and group ownership and mode bits, to control which data each user can access on a shared filesystem.

Current user execution governs identity, not process isolation. Connect already isolates content processes from one another regardless of which Unix account they run as, through sandboxing on local execution and through container isolation in off-host (Kubernetes) deployments. Use current user execution when you need the operating system to enforce per-user data access, not to separate processes.

This identity model has a cost. Under the shared account, Connect can serve many viewers of an application from a single process. Because each viewer’s process runs under a different Unix account, current user execution removes that sharing: every concurrent viewer spawns a dedicated process. An application’s process count, and its memory and CPU use, then grow with the size of its audience. Plan capacity for the number of concurrent viewers rather than the number of connections, review the application’s process settings, and see Sizing and capacity planning for guidance.

Alternatives to current user execution

Current user execution adds operational complexity and increases resource usage. Before adopting it, compare the approaches below to decide which one fits your needs:

Approach Use it to Server processes
Current user execution Control access to data on a shared filesystem using Unix permissions. Each concurrent viewer runs in a dedicated process under their own Unix account. Connect cannot share a process across viewers, so process count and resource use grow with the audience.
OAuth integration Authorize downstream data access (databases, APIs, cloud services) per viewer, without changing the Unix account the process runs as. Shared. A single process can serve many viewers, up to its configured maximum connections per process.
Per-content RunAs user Run specific content under a specific, non-default Unix account. Assign different accounts to different content to model group-based data access with Unix group permissions, without per-viewer execution. Shared. A single process can serve many viewers.
Shared rstudio-connect account (default) Keep the recommended default. No configuration required. Shared. A single process can serve many viewers.

If your only requirement is that content authenticates to an external system as the viewer, an OAuth integration is usually the better choice, and it avoids the per-user process overhead. Reach for current user execution when you need to control access to data on a shared filesystem using Unix permissions, and you have accounted for its effect on server resources.

Prerequisites

Before you begin, you must have:

  • A Connect Enhanced or Advanced license.
  • A Connect installation that uses OAuth 2.0, SAML, or LDAP authentication, or, for local execution only, PAM authentication. Current user execution does not support Proxied or Password authentication.
  • Administrator access to the Connect server and its configuration file.
  • The ability to manage Unix accounts and group membership on the Connect server (or, for off-host execution, in your container images).

Choose how Connect resolves Unix identity

Current user execution requires Connect to map each logged-in user to a Unix account. Two identity sources are supported. The choice determines what you set up in Step 1 and how you satisfy the group membership requirement in Step 3, so decide before you begin.

Connect Nameservice. The Connect Nameservice derives each user’s Unix identity from your authentication provider. With LDAP authentication, Connect reads Unix attributes from your directory at login through LDAP.PosixUsernameAttribute and LDAP.PosixUIDAttribute. With OAuth 2.0 or SAML, the identity arrives in token claims or assertions. If no Unix identity is sent from the IdP, the nameservice provisions a unique Unix account for each user automatically. Choose the nameservice when you authenticate with LDAP, or when your identity provider can send Unix identities.

SSSD. The System Security Services Daemon (SSSD) resolves Unix identity directly from a directory service such as LDAP or Active Directory, independent of the authentication provider. Connect resolves the content process’s UID and GID through the operating system Name Service Switch (NSS) on the Connect server, and when SSSD is the configured NSS source, those lookups return the directory’s values: the user’s uidNumber and group memberships. The process’s primary group comes from Applications.SharedRunAsUnixGroup and the user’s directory groups apply as supplementary groups. Choose SSSD when your directory is the source of truth for Unix identity and you authenticate with OAuth 2.0 or SAML. Your tokens or assertions then only need to carry a username SSSD can resolve, not a Unix UID. With LDAP authentication you do not need SSSD, since Connect already reads your directory at login.

PAM. If you authenticate with PAM, no identity source is needed; PAM users are already operating system accounts. PAM is supported for local execution only. See PAM sessions in the Admin Guide for the PAM-specific setup, including credential caching for Kerberos, and skip Step 1.

Step 1: Set up identity resolution

Set up the identity source you chose above. If you authenticate with PAM, skip this step.

Connect Nameservice

Configure the nameservice by following the Connect Nameservice guide, which covers both local and off-host (Kubernetes) execution, user mapping options, and verification.

SSSD

To resolve identity with SSSD, you need:

  • OAuth 2.0 or SAML authentication, with the Unix username claim or attribute set to a value SSSD can resolve, which is typically sAMAccountName for Active Directory. Use OAuth2.PosixUsernameClaim or SAML.PosixUsernameAttribute. Do not set a Unix UID claim or attribute. The directory supplies the UID.
  • SSSD running with an LDAP or Active Directory provider, with the nss service enabled in sssd.conf and sss listed for the passwd, group, and initgroups databases in /etc/nsswitch.conf. The off-host example below configures all of this. For local execution, follow your distribution’s SSSD documentation.
  • The libnss_sss client library on the hosts where Connect runs. This is a declared dependency for Connect installations on Debian, Ubuntu, and RHEL and should be installed with Connect; SUSE administrators may need to install sssd.

SSSD works with both local and off-host execution. On local execution, configure SSSD on each Connect server as you would for any Linux host. For off-host execution on Kubernetes, run SSSD as a sidecar of the Connect server pod, as shown below.

Configure an off-host SSSD sidecar

The following values.yaml disables the nameservice module, supplies nsswitch.conf through a ConfigMap and sssd.conf through a Secret, runs SSSD as a sidecar that shares its runtime directory with the Connect container, and points the Name Service Switch at SSSD. This example uses an LDAP provider with a bind password. sssd.conf holds that credential, so it goes in a Secret. For an Active Directory provider that authenticates with a keytab, mount the keytab from its own Secret and reference its path in sssd.conf. Adapt the values to your directory.

values.yaml
# Do not activate the Connect nameservice module. Unix identity comes from SSSD.
nameservice:
  enabled: false

config:
  Applications:
    RunAsCurrentUser: true
    # A directory group that every current user execution user belongs to,
    # including the default Applications.RunAs service account. SSSD must
    # resolve it, and Connect uses it as the content pod's primary group.
    SharedRunAsUnixGroup: connect-users

extraObjects:
  # nsswitch.conf routes passwd, group, and initgroups to SSSD.
  - apiVersion: v1
    kind: ConfigMap
    metadata:
      name: connect-nsswitch
    data:
      nsswitch.conf: |
        passwd:     files sss
        group:      files sss
        initgroups: files sss
        shadow:     files sss
        hosts:      files dns
  # sssd.conf points at your directory and contains the bind password, so it is
  # a Secret. SSSD requires this file to have mode 0600.
  - apiVersion: v1
    kind: Secret
    metadata:
      name: connect-sssd-conf
    stringData:
      sssd.conf: |
        [sssd]
        services = nss
        domains = mydirectory

        [nss]

        [domain/mydirectory]
        id_provider = ldap
        ldap_uri = ldaps://ldap.example.com
        ldap_search_base = dc=example,dc=com
        ldap_default_bind_dn = cn=connect,ou=service,dc=example,dc=com
        ldap_default_authtok_type = password
        ldap_default_authtok = "<your directory bind password>"

pod:
  # An image that contains the sssd daemon and an LDAP or AD provider.
  # The shared emptyDir hides the /var/lib/sss runtime directories baked into
  # the image, so recreate them before starting the daemon.
  sidecar:
    - name: sssd
      image: <your sssd image>
      command: ["/bin/sh", "-c"]
      args:
        - |
          mkdir -p /var/lib/sss/db /var/lib/sss/mc /var/lib/sss/pipes/private
          exec /usr/sbin/sssd -i --logger=stderr
      volumeMounts:
        - name: sssd-runtime
          mountPath: /var/lib/sss
        - name: sssd-conf
          mountPath: /etc/sssd/sssd.conf
          subPath: sssd.conf
  volumes:
    - name: sssd-runtime
      emptyDir: {}
    - name: sssd-conf
      secret:
        secretName: connect-sssd-conf
        defaultMode: 0600
    - name: nsswitch
      configMap:
        name: connect-nsswitch
  # Share the SSSD runtime directory so the in-container NSS client reaches the
  # daemon, and replace nsswitch.conf so lookups route to SSSD.
  volumeMounts:
    - name: sssd-runtime
      mountPath: /var/lib/sss
    - name: nsswitch
      mountPath: /etc/nsswitch.conf
      subPath: nsswitch.conf

Deploy or upgrade your Helm release with the updated values:

Terminal
helm upgrade --install connect rstudio/rstudio-connect \
  --namespace <your-connect-namespace> \
  -f values.yaml

Verify the SSSD configuration

On the Connect server, confirm that SSSD resolves your users and the shared group:

Terminal
getent passwd <username>
getent group <shared-group>
id <username>

getent passwd must return the directory uidNumber, and id must list the expected groups, including the Applications.SharedRunAsUnixGroup group. If a user does not resolve, check that the value from your Unix username claim or attribute matches a directory account SSSD can resolve. After completing the remaining steps, launch content as that user and confirm the process runs with the directory UID.

Step 2: Allow current user execution on the server

Set Applications.RunAsCurrentUser to true in the Connect configuration file:

/etc/rstudio-connect/rstudio-connect.gcfg
[Applications]
RunAsCurrentUser = true

Restart Connect to apply the change.

This setting permits current user execution but does not change how any existing content runs. You must still configure each application individually to request it, as described in Step 4. Content you have not configured for current user execution continues to run as the RunAs user.

Step 3: Confirm Unix accounts have the required group membership

Every Unix account used to run content must belong to the group named by Applications.SharedRunAsUnixGroup. This applies to each viewer’s Unix account, not only the default service account. An application fails to launch if the account associated with the logged-in user is not a member of this group.

How you satisfy this requirement depends on your identity source:

  • Accounts the nameservice provisions automatically: The nameservice sets each new account’s group to Applications.SharedRunAsUnixGroup, so membership is handled for you. No action is needed.
  • Existing accounts you map through the nameservice, or accounts used with PAM: You must add each account to the Applications.SharedRunAsUnixGroup group yourself.
  • Accounts resolved through SSSD: Point Applications.SharedRunAsUnixGroup at a directory group and make every current user execution user a member, including the default Applications.RunAs service account. Supplementary group memberships come from the directory, so you do not assign group IDs (GIDs) to Connect groups, and a group’s directory GID must match the GID that owns the files or appears in the access control list on the file server.

When you use the default RunAs user, the relevant group is rstudio-connect.

Step 4: Configure content to run as the current user

By default, only administrators can change process execution. Publishers can set it for content they own or collaborate on when Authorization.PublishersCanManageRunAs is true.

In the Connect dashboard, set the content’s process owner to the current user. For the steps and the full set of options, see Changing the process owner in the User Guide.

You can also configure this programmatically. The run_as_current_user field on the create and update content API endpoints toggles current user execution for a content item.

When someone accesses the content anonymously, it runs as the configured fallback RunAs user instead of a per-user account.

File permissions considerations

Because each viewer’s process runs under a different Unix account, another user who opens the same application might not be able to read files that the first user wrote to the working directory. A file with restrictive permissions, such as mode 0400, can cause failures for other viewers.

All accounts used for current user execution share membership in Applications.SharedRunAsUnixGroup, so set group-readable permissions explicitly on any files your application writes and needs to share. For details and recommendations, see Writing data to the working directory.