> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.nvidia.com/infra-controller/llms.txt.
> For full documentation content, see https://docs.nvidia.com/infra-controller/llms-full.txt.

## Visual Studio Code Remote Docker Workflow

This page describes a workflow on how to build and test NCX Infra Controller (NICo) inside a remotely
running docker container. The advantage of this workflow is that it requires no tools
to be installed on your native Machine, but still can provide you a similar
development feeling.

### Prerequisites

- Install Visual Studio Code from [https://code.visualstudio.com](https://code.visualstudio.com)
- Install the [Remote Development Extension Pack](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack)
- Enable the `code` command for MacBook:
    - Open VS Code
    - Press `Cmd + Shift + P` to open the Command Palette.
    - Type `Shell Command: Install 'code' command in PATH` and select it. This sets up the code command for your terminal.
- On the remote server, update the SSH daemon configuration to support port forwarding:
    - Edit the sshd configuration file:
        ```
        doas vi /etc/ssh/sshd_config
        ```
    - Add or update the following lines:
        ```
        AllowTcpForwarding yes
        GatewayPorts yes
        ```
    - Restart sshd daemon:
        ```
        doas systemctl restart sshd
        ```
    - For MacBook:
      - Port forwarding may fail initially.
      - To resolve this issue, remove the `~/.ssh/known_hosts` file.
    *Source*: [Stack Overflow](https://stackoverflow.com/questions/75837749/vscode-failed-to-set-up-socket-for-dynamic-port-forward-to-remote-port-connect)
      - **Note**: Be sure to back up the file before deleting it.

### Basic remote setup

Start `VS Code` using the `code` command in the same shell after running `nvinit`:

Click the remote button on the lower left of the IDE window:
![](https://files.buildwithfern.com/nvidia-ncx-infra-controller.docs.buildwithfern.com/infra-controller/0e1f3493d0467325bacb022d34a0ff9462c1c3ea9e4c28c747080127d5ffa664/_dot_dot_/docs/static/remote_button.png).
Select "Connect to Host", choose the remote hostname defined in [Prerequisites](#Prerequisites), and connect. A new Visual Studio Code window should open, which is now on that host.
Inside that window, open the folder which contains the NICo project.

Assuming that remote machine already has all dev tools installed, and you want to
work directly on the machine instead of inside a container, you could open up
Visual Studio Code's integrated terminal, and for example run:
```
cd api
cargo test
```

### Remote Rust Analyzer support

In order to get proper IDE support also while working on the remote host,
you can install the "Rust Analyzer" extension on the remote host. To do so:
- Open the extensions tab
- Look for the second column in it, which is labeled: `SSH: $hostname - Installed`.
- Click the download button next to it.
- Select Rust Analyzer, and all other extensions you want to install on the remote Host.
  Other recommended extensions are CodeLLDB for debugging Rust code, Better TOML
  for editing `.toml` files, and GitLens.

### Remote container setup

On top of developing on a remote host, one can develop inside a container that
contains all dev tools. The container can either run locally (if you work on a Linux machine),
or on a remote Linux machine.

To work inside the remote container, the following steps are performed:
- Inside the NICo directory on the Linux host you are working on, place a
    `.devcontainer/devcontainer.json` file with the following details
    ```json
    // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
    // https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/docker-existing-dockerfile
    {
        "name": "Existing Dockerfile",

        // Sets the run context to one level up instead of the .devcontainer folder.
        "context": "../dev/docker/",

        // Update the 'dockerFile' property if you aren't using the standard 'Dockerfile' filename.
        // "dockerFile": "../Dockerfile",
        "dockerFile": "../dev/docker/Dockerfile.build-container-x86_64",

        // Use 'forwardPorts' to make a list of ports inside the container available locally.
        // "forwardPorts": [],

        // Uncomment the next line to run commands after the container is created - for example installing curl.
        // "postCreateCommand": "apt-get update && apt-get install -y curl",

        // Uncomment when using a ptrace-based debugger like C++, Go, and Rust
        "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined" ],

        // Uncomment to use the Docker CLI from inside the container. See https://aka.ms/vscode-remote/samples/docker-from-docker.
        "mounts": [ "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" ]

        // Uncomment to connect as a non-root user if you've added one. See https://aka.ms/vscode-remote/containers/non-root.
        //"remoteUser": "youralias"
    }
    ```
    This will automatically instruct the remote container extension to pick the specified container image.
    The build container image is picked here, because it contains all necessary tools.
2. Click the remote button on the lower left of the IDE window:
![](https://files.buildwithfern.com/nvidia-ncx-infra-controller.docs.buildwithfern.com/infra-controller/0e1f3493d0467325bacb022d34a0ff9462c1c3ea9e4c28c747080127d5ffa664/_dot_dot_/docs/static/remote_button.png). Select "Reopen in Container". Since a container configuration
    file for the project exists, Visual Studio Code should automatically build the specified
    `Dockerfile`, launch it as a container, install a VsCode remote server in it,
    and launch your editor window in it.
3. The new editor window runs inside the container, and should show something along
    "Dev Container: Existing Dockerfile" on the lower left.
4. You can again open an integrated terminal here, and build the project.
5. The dev container again has a separate set of installed extensions. You will
    need to reinstall all extensions you need there - e.g. Rust Analyzer.

### Enabling postgres inside the dev container

While the last step will allow you to build the project and run some unit tests,
all unit tests which require a database will fail. To fix this, start the postgres
server inside the development container:

1. Open another internal terminal tab
2. Start postgres:
    ```
    /etc/init.d/postgresql start
    ```
3. Create the user:
    ```
    su postgres -c "/usr/lib/postgresql/15/bin/createuser -d root"
    ```
4. Set permissions:
    ```
    sudo -u postgres psql -c "ALTER USER root WITH SUPERUSER;"
    ```
5. Create a database:
    ```
    createdb root
    ```
6. Set the `DATABASE_URL` environment variable:
    ```
    export DATABASE_URL="postgresql://%2Fvar%2Frun%2Fpostgresql"
    ```

With those steps completed, running `cargo test` should succeed.

If you also want to run or debug unit-test from within Visual Studio code
using the inline buttons "**Run Test**" and "**Debug**" that Rust-Analyzer
adds, you have to add the following configuration to the Visual Studio Code
json config file:
```json
"rust-analyzer.runnableEnv": {
    "DATABASE_URL": "postgresql://%2Fvar%2Frun%2Fpostgresql"
}
```

### Gotchas

- If you work as `root` inside the dev container, editing files might make them
  owned by `root`, which can prevent working on them from your regular desktop.
  You might need to reset ownership when going back to your regular environment:
  ```
  sudo chown -R yourAlias carbide/*
  ```
- The same applies for using git inside the container as root. It will make
  files in `.git` be owned by `root`

Those problems might be avoidable by being able to set `remoteUser` in `devcontainer.json`
to one's alias. However when doing that I wasn't able to build the devcontainer image
anymore, since it is missing my user alias in `/etc/passwd`.


### References

- [https://code.visualstudio.com/docs/remote/remote-overview](https://code.visualstudio.com/docs/remote/remote-overview)