# Container (non-root) user can't write to /dev/stdout or /dev/stderr

**URL:** <https://community.fly.io/t/container-non-root-user-cant-write-to-dev-stdout-or-dev-stderr/10375>\
**Category:** General\
**Created:** [January 26, 2023, 5:50pm UTC](https://community.fly.io/t/container-non-root-user-cant-write-to-dev-stdout-or-dev-stderr/10375 "2023-01-26T17:50:28Z")\
**Posts on this page:** 1\
**Showing post:** 13

<div class="post-metadata">

**Author:** ![tom93](https://avatars.discourse-cdn.com/v4/letter/t/dec6dc/32.png) [@tom93](https://community.fly.io/u/tom93)\
**Post date:** [January 28, 2023, 10:46am UTC](https://community.fly.io/t/container-non-root-user-cant-write-to-dev-stdout-or-dev-stderr/10375/13 "2023-01-28T10:46:18Z")

</div>

> [@ignoramous](#):
>
> > [@tom93](#):
> >
> > ```plaintext
> > # cmd='whoami; ls -l /dev/stdout /proc/self/fd/1; echo "test" >>/dev/stdout'
> > # su -s /bin/sh -c "$cmd" www-data >/tmp/out
> > 
> > ```
> 
> Will you pls explain what these two lines test? I can see that the string `test` wouldn’t append to `/tmp/out` (which is a regular file?), but have trouble understanding how `/tmp/out` became a `stdout` sink and why `/bin/sh -c ... >/tmp/out` didn’t (or isn’t expected to) truncate `/tmp/out`…?

Oh yeah, that wasn’t very self-explanatory. Here is a simplified version:

```auto
su -s /bin/sh -c 'echo "test 1"; echo "test 2" >>/dev/stdout' www-data >/tmp/out

```

Here /tmp/out is a regular file which is _only writable by root_. The aim is to get the “inner” command (two echo’s) to run as user www-data with fd 1 open to /tmp/out. The outer command achieves this by calling `su` and redirecting output to /tmp/out.

The first `echo` succeeds (and the output is saved in /tmp/out) _even though www-data doesn’t have write access to /tmp/out_. The second `echo` seems to be equivalent (because /dev/stdout is normally equivalent to fd 1), but it fails because /dev/stdout is a symlink to /proc/self/fd/1 which is a symlink to /tmp/out and opening it triggers a permission check which fails.

In the `su` invocation, the option `-s /bin/sh` is required because the default shell of www-data is /usr/sbin/nologin.  
Changing `>>/dev/stdout` to `>/dev/stdout` doesn’t make a difference.

* * *

> [@ignoramous](#):
>
> > [@Alex21](#):
> >
> > But if there’s a way to launch an app/machine as the root user regardless of the user instruction that’s in the image, then doing that
> 
> Yes, via the `experimental` section of an app’s `fly.toml` ([docs](https://fly.io/docs/reference/configuration/#the-experimental-section), [ref](https://community.fly.io/t/unable-to-deploy-non-phoenix-elixir-app/2164/8)), or the `processes` section (where `app` is the default name for an entrypoint / main process on Fly):

The `experimental` section only has `cmd` and `entrypoint` (and `exec`), it doesn’t have `user`.

---

_[View the full topic](https://community.fly.io/t/container-non-root-user-cant-write-to-dev-stdout-or-dev-stderr/10375)._
