From 78e395e14ab18ecb3ef42185bcb17a1d9c5ad295 Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Tue, 6 Dec 2022 22:41:23 +1000 Subject: [PATCH 01/17] feat(dogfood): install nix package manager --- dogfood/Dockerfile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index c96ee1fd2d78e..6715e16393450 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -312,8 +312,17 @@ COPY --from=go /tmp/bin /usr/local/bin COPY --from=rust-utils /tmp/bin /usr/local/bin COPY --from=proto /tmp/bin /usr/local/bin +# Configure Nix without sandboxing - https://github.com/NixOS/nix/issues/2636#issuecomment-455302745 +RUN mkdir -p /nix /etc/nix \ + && chmod a+rwx /nix \ + && echo 'sandbox = false' > /etc/nix/nix.conf + + USER coder +# Install Nix +RUN sh <(curl -L https://nixos.org/nix/install) --no-daemon + # Ensure go bins are in the 'coder' user's path. Note that no go bins are # installed in this docker file, as they'd be mounted over by the persistent # home volume. From f166695c0704e099b140ba62f2f363a1b8de064b Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Tue, 6 Dec 2022 22:42:35 +1000 Subject: [PATCH 02/17] Update dogfood/Dockerfile --- dogfood/Dockerfile | 1 - 1 file changed, 1 deletion(-) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index 6715e16393450..fafd2867cbd12 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -317,7 +317,6 @@ RUN mkdir -p /nix /etc/nix \ && chmod a+rwx /nix \ && echo 'sandbox = false' > /etc/nix/nix.conf - USER coder # Install Nix From ee4f7b64c3c463cfcef8d15cf666995133574367 Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Tue, 6 Dec 2022 23:04:58 +1000 Subject: [PATCH 03/17] enable unfree and source in bashprofile --- dogfood/Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index fafd2867cbd12..6d00a3c95f7b0 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -322,6 +322,9 @@ USER coder # Install Nix RUN sh <(curl -L https://nixos.org/nix/install) --no-daemon +RUN echo '. /home/coder/.nix-profile/etc/profile.d/nix.sh' >> /home/coder/.bashrc +RUN mkdir -p /home/coder/.config/nixpkgs && echo '{ allowUnfree = true; }' >> /home/coder/.config/nixpkgs/config.nix + # Ensure go bins are in the 'coder' user's path. Note that no go bins are # installed in this docker file, as they'd be mounted over by the persistent # home volume. From 22b2535bb2f2d30176b677b7ad2e61cf4f81a63d Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Wed, 7 Dec 2022 01:09:38 +1000 Subject: [PATCH 04/17] style/linting adjustments. Co-authored-by: Dean Sheather --- dogfood/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index 6d00a3c95f7b0..6c335e9e7adb4 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -313,9 +313,9 @@ COPY --from=rust-utils /tmp/bin /usr/local/bin COPY --from=proto /tmp/bin /usr/local/bin # Configure Nix without sandboxing - https://github.com/NixOS/nix/issues/2636#issuecomment-455302745 -RUN mkdir -p /nix /etc/nix \ - && chmod a+rwx /nix \ - && echo 'sandbox = false' > /etc/nix/nix.conf +RUN mkdir -p /nix /etc/nix && \ + chmod a+rwx /nix && \ + echo 'sandbox = false' > /etc/nix/nix.conf USER coder From 8ac9021a07eb5f0f443ce8941ac941727478671a Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Wed, 7 Dec 2022 01:24:11 +1000 Subject: [PATCH 05/17] add comments --- dogfood/Dockerfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index 6c335e9e7adb4..5eac5145b408d 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -322,7 +322,10 @@ USER coder # Install Nix RUN sh <(curl -L https://nixos.org/nix/install) --no-daemon +# Install Nix into our bash profile so `nix-shell`, `nix-build, and `nix` are available RUN echo '. /home/coder/.nix-profile/etc/profile.d/nix.sh' >> /home/coder/.bashrc + +# Enable installation of unfree software - https://nixos.wiki/wiki/FAQ/How_can_I_install_a_proprietary_or_unfree_package RUN mkdir -p /home/coder/.config/nixpkgs && echo '{ allowUnfree = true; }' >> /home/coder/.config/nixpkgs/config.nix # Ensure go bins are in the 'coder' user's path. Note that no go bins are From 7984ed7d64b5cd582139b3442434fb01603cc794 Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Wed, 7 Dec 2022 01:26:36 +1000 Subject: [PATCH 06/17] ensure coder user can write to /nix --- dogfood/Dockerfile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index 5eac5145b408d..807828b3fdde3 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -313,9 +313,11 @@ COPY --from=rust-utils /tmp/bin /usr/local/bin COPY --from=proto /tmp/bin /usr/local/bin # Configure Nix without sandboxing - https://github.com/NixOS/nix/issues/2636#issuecomment-455302745 -RUN mkdir -p /nix /etc/nix && \ - chmod a+rwx /nix && \ - echo 'sandbox = false' > /etc/nix/nix.conf +RUN addgroup --system nixbld \ + && adduser coder nixbld \ + && for i in $(seq 1 30); do useradd -ms /bin/bash nixbld$i && adduser nixbld$i nixbld; done \ + && mkdir -m 0755 /nix && chown coder /nix \ + && mkdir -p /etc/nix && echo 'sandbox = false' > /etc/nix/nix.conf USER coder From 41d1aefb2dcd6c36f79479a8684361c6279f3579 Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Thu, 8 Dec 2022 22:12:14 +1000 Subject: [PATCH 07/17] chown coder:coder /nix Co-authored-by: Mathias Fredriksson --- dogfood/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index 807828b3fdde3..9b2607a216c13 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -316,7 +316,7 @@ COPY --from=proto /tmp/bin /usr/local/bin RUN addgroup --system nixbld \ && adduser coder nixbld \ && for i in $(seq 1 30); do useradd -ms /bin/bash nixbld$i && adduser nixbld$i nixbld; done \ - && mkdir -m 0755 /nix && chown coder /nix \ + && mkdir -m 0755 /nix && chown coder:coder /nix \ && mkdir -p /etc/nix && echo 'sandbox = false' > /etc/nix/nix.conf USER coder From 25b1ac34ce0a4cc959bebf4dfe6d1e516b0c6aea Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Thu, 8 Dec 2022 22:13:47 +1000 Subject: [PATCH 08/17] add further comments --- dogfood/Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index 9b2607a216c13..2b5170c3ec5dd 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -312,7 +312,9 @@ COPY --from=go /tmp/bin /usr/local/bin COPY --from=rust-utils /tmp/bin /usr/local/bin COPY --from=proto /tmp/bin /usr/local/bin -# Configure Nix without sandboxing - https://github.com/NixOS/nix/issues/2636#issuecomment-455302745 +# Configure Nix without sandboxing +# - https://github.com/NixOS/nix/issues/2636#issuecomment-455302745 +# - https://nixos.org/manual/nix/stable/installation/multi-user.html#setting-up-the-build-users RUN addgroup --system nixbld \ && adduser coder nixbld \ && for i in $(seq 1 30); do useradd -ms /bin/bash nixbld$i && adduser nixbld$i nixbld; done \ From 0872948eba1c0de75d643eb8b84ab225420ac104 Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Mon, 12 Dec 2022 03:28:56 +0000 Subject: [PATCH 09/17] =?UTF-8?q?=F0=9F=8E=B6=20https://www.youtube.com/wa?= =?UTF-8?q?tch=3Fv=3DoRdxUFDoQe0=20pin=20it,=20just=20pin=20it?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dogfood/Dockerfile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index 2b5170c3ec5dd..4abeab15258d2 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -324,7 +324,14 @@ RUN addgroup --system nixbld \ USER coder # Install Nix -RUN sh <(curl -L https://nixos.org/nix/install) --no-daemon +export NIX_VERSION=2.3.15 +RUN curl --silent --show-error --location \ + "https://releases.nixos.org/nix/nix-${NIX_VERSION}/nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ + -o "nix-${NIX_VERSION}-x86_64-linux.tar.xz" + +RUN tar -xf "nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ + && bash "nix-${NIX_VERSION}-x86_64-linux/install" "--no-daemon" \ + && rm -rf "nix-${NIX_VERSION}-x86_64-linux.tar.xz" # Install Nix into our bash profile so `nix-shell`, `nix-build, and `nix` are available RUN echo '. /home/coder/.nix-profile/etc/profile.d/nix.sh' >> /home/coder/.bashrc From a5164134387007685bd90ad14ededd6a8e9b123e Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Mon, 12 Dec 2022 03:36:28 +0000 Subject: [PATCH 10/17] hopefully the final review iteration, thanks for your help! --- dogfood/Dockerfile | 3 --- dogfood/main.tf | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index 4abeab15258d2..85ffa612b4026 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -333,9 +333,6 @@ RUN tar -xf "nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ && bash "nix-${NIX_VERSION}-x86_64-linux/install" "--no-daemon" \ && rm -rf "nix-${NIX_VERSION}-x86_64-linux.tar.xz" -# Install Nix into our bash profile so `nix-shell`, `nix-build, and `nix` are available -RUN echo '. /home/coder/.nix-profile/etc/profile.d/nix.sh' >> /home/coder/.bashrc - # Enable installation of unfree software - https://nixos.wiki/wiki/FAQ/How_can_I_install_a_proprietary_or_unfree_package RUN mkdir -p /home/coder/.config/nixpkgs && echo '{ allowUnfree = true; }' >> /home/coder/.config/nixpkgs/config.nix diff --git a/dogfood/main.tf b/dogfood/main.tf index 32640baf70aaa..90ebc41575d43 100644 --- a/dogfood/main.tf +++ b/dogfood/main.tf @@ -56,6 +56,11 @@ resource "coder_agent" "dev" { if [ -n "$DOTFILES_URI" ]; then coder dotfiles "$DOTFILES_URI" -y 2>&1 | tee ~/.personalize.log fi + + + # Install Nix into our bash profile so `nix-shell`, `nix-build, and `nix` are available + echo '. /home/coder/.nix-profile/etc/profile.d/nix.sh' >> /home/coder/.bashrc + bash /opt/nix/install --no-daemon EOF } @@ -102,6 +107,33 @@ resource "docker_volume" "home_volume" { } } +resource "docker_volume" "nix_volume" { + name = "coder-${data.coder_workspace.me.id}-nix" + # Protect the volume from being deleted due to changes in attributes. + lifecycle { + ignore_changes = all + } + # Add labels in Docker to keep track of orphan resources. + labels { + label = "coder.owner" + value = data.coder_workspace.me.owner + } + labels { + label = "coder.owner_id" + value = data.coder_workspace.me.owner_id + } + labels { + label = "coder.workspace_id" + value = data.coder_workspace.me.id + } + # This field becomes outdated if the workspace is renamed but can + # be useful for debugging or cleaning out dangling volumes. + labels { + label = "coder.workspace_name_at_creation" + value = data.coder_workspace.me.name + } +} + resource "coder_metadata" "home_info" { resource_id = docker_volume.home_volume.id item { @@ -153,6 +185,11 @@ resource "docker_container" "workspace" { volume_name = docker_volume.home_volume.name read_only = false } + volumes { + container_path = "/nix" + volume_name = docker_volume.nix_volume.name + read_only = false + } # Add labels in Docker to keep track of orphan resources. labels { label = "coder.owner" From 68402a9d75f5a312755e674d99131c301116dbfa Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Mon, 12 Dec 2022 04:30:10 +0000 Subject: [PATCH 11/17] arg not export --- dogfood/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index 85ffa612b4026..a02079a7927ba 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -324,7 +324,7 @@ RUN addgroup --system nixbld \ USER coder # Install Nix -export NIX_VERSION=2.3.15 +ARG NIX_VERSION=2.3.15 RUN curl --silent --show-error --location \ "https://releases.nixos.org/nix/nix-${NIX_VERSION}/nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ -o "nix-${NIX_VERSION}-x86_64-linux.tar.xz" From fb1eac831cddc66b99b305c28dcc151c924c8a85 Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Thu, 22 Dec 2022 17:33:00 +1030 Subject: [PATCH 12/17] Update dogfood/Dockerfile Co-authored-by: Mathias Fredriksson --- dogfood/Dockerfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index a02079a7927ba..0ea88dd5d2100 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -325,12 +325,12 @@ USER coder # Install Nix ARG NIX_VERSION=2.3.15 -RUN curl --silent --show-error --location \ +RUN cd /opt \ + && curl --silent --show-error --location \ "https://releases.nixos.org/nix/nix-${NIX_VERSION}/nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ - -o "nix-${NIX_VERSION}-x86_64-linux.tar.xz" - -RUN tar -xf "nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ - && bash "nix-${NIX_VERSION}-x86_64-linux/install" "--no-daemon" \ + -o "nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ + && tar -xf "nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ + && ln -s "nix-${NIX_VERSION}-x86_64-linux" nix \ && rm -rf "nix-${NIX_VERSION}-x86_64-linux.tar.xz" # Enable installation of unfree software - https://nixos.wiki/wiki/FAQ/How_can_I_install_a_proprietary_or_unfree_package From ec10dc1323e1dd9f1ce9fd9a6ffae1905f213c67 Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Thu, 22 Dec 2022 07:10:39 +0000 Subject: [PATCH 13/17] line now exists in main.tf --- dogfood/Dockerfile | 3 --- 1 file changed, 3 deletions(-) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index 0ea88dd5d2100..43f4dcf29e39b 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -333,9 +333,6 @@ RUN cd /opt \ && ln -s "nix-${NIX_VERSION}-x86_64-linux" nix \ && rm -rf "nix-${NIX_VERSION}-x86_64-linux.tar.xz" -# Enable installation of unfree software - https://nixos.wiki/wiki/FAQ/How_can_I_install_a_proprietary_or_unfree_package -RUN mkdir -p /home/coder/.config/nixpkgs && echo '{ allowUnfree = true; }' >> /home/coder/.config/nixpkgs/config.nix - # Ensure go bins are in the 'coder' user's path. Note that no go bins are # installed in this docker file, as they'd be mounted over by the persistent # home volume. From fd882b2d612feee365edf9234a05794481127757 Mon Sep 17 00:00:00 2001 From: Geoffrey Huntley Date: Thu, 22 Dec 2022 07:11:31 +0000 Subject: [PATCH 14/17] remove whitespace --- dogfood/main.tf | 1 - 1 file changed, 1 deletion(-) diff --git a/dogfood/main.tf b/dogfood/main.tf index 90ebc41575d43..23c6135d96f3c 100644 --- a/dogfood/main.tf +++ b/dogfood/main.tf @@ -57,7 +57,6 @@ resource "coder_agent" "dev" { coder dotfiles "$DOTFILES_URI" -y 2>&1 | tee ~/.personalize.log fi - # Install Nix into our bash profile so `nix-shell`, `nix-build, and `nix` are available echo '. /home/coder/.nix-profile/etc/profile.d/nix.sh' >> /home/coder/.bashrc bash /opt/nix/install --no-daemon From 4160ad488434a37f5b7caf58f53ab8cd4ffa1e1f Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Tue, 17 Jan 2023 14:50:22 +0000 Subject: [PATCH 15/17] Apply @mafredri's suggestion --- dogfood/main.tf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dogfood/main.tf b/dogfood/main.tf index 201c82d2a569b..d81aed2249c7d 100644 --- a/dogfood/main.tf +++ b/dogfood/main.tf @@ -71,8 +71,10 @@ resource "coder_agent" "dev" { sudo service docker start # Install Nix into our bash profile so `nix-shell`, `nix-build, and `nix` are available - echo '. /home/coder/.nix-profile/etc/profile.d/nix.sh' >> /home/coder/.bashrc bash /opt/nix/install --no-daemon + if ! grep -q '. ~/.nix-profile/etc/profile.d/nix.sh' ~/.bashrc; then + echo '. ~/.nix-profile/etc/profile.d/nix.sh' >> ~/.bashrc + fi DOTFILES_URI=${var.dotfiles_uri} if [ -n "$DOTFILES_URI" ]; then From 9417529199c99c57cb3db02dea04c2934f38a2de Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 17 Jan 2023 16:22:54 +0000 Subject: [PATCH 16/17] Fix user --- dogfood/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index 013b45c27a662..bb48cb6ffba81 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -325,8 +325,6 @@ RUN addgroup --system nixbld \ && mkdir -m 0755 /nix && chown coder:coder /nix \ && mkdir -p /etc/nix && echo 'sandbox = false' > /etc/nix/nix.conf -USER coder - # Install Nix ARG NIX_VERSION=2.3.15 RUN cd /opt \ @@ -351,3 +349,5 @@ ENV GOPRIVATE="coder.com,cdr.dev,go.coder.com,github.com/cdr,github.com/coder" # Increase memory allocation to NodeJS ENV NODE_OPTIONS="--max-old-space-size=8192" + +USER coder \ No newline at end of file From d89f634af7004c3e85f5acdfcc928644cf684f14 Mon Sep 17 00:00:00 2001 From: Mathias Fredriksson Date: Tue, 17 Jan 2023 16:24:44 +0000 Subject: [PATCH 17/17] Match indent --- dogfood/Dockerfile | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/dogfood/Dockerfile b/dogfood/Dockerfile index bb48cb6ffba81..f9b48a8873e6f 100644 --- a/dogfood/Dockerfile +++ b/dogfood/Dockerfile @@ -320,20 +320,20 @@ COPY --from=proto /tmp/bin /usr/local/bin # - https://github.com/NixOS/nix/issues/2636#issuecomment-455302745 # - https://nixos.org/manual/nix/stable/installation/multi-user.html#setting-up-the-build-users RUN addgroup --system nixbld \ - && adduser coder nixbld \ - && for i in $(seq 1 30); do useradd -ms /bin/bash nixbld$i && adduser nixbld$i nixbld; done \ - && mkdir -m 0755 /nix && chown coder:coder /nix \ - && mkdir -p /etc/nix && echo 'sandbox = false' > /etc/nix/nix.conf + && adduser coder nixbld \ + && for i in $(seq 1 30); do useradd -ms /bin/bash nixbld$i && adduser nixbld$i nixbld; done \ + && mkdir -m 0755 /nix && chown coder:coder /nix \ + && mkdir -p /etc/nix && echo 'sandbox = false' > /etc/nix/nix.conf # Install Nix ARG NIX_VERSION=2.3.15 RUN cd /opt \ - && curl --silent --show-error --location \ - "https://releases.nixos.org/nix/nix-${NIX_VERSION}/nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ - -o "nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ - && tar -xf "nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ - && ln -s "nix-${NIX_VERSION}-x86_64-linux" nix \ - && rm -rf "nix-${NIX_VERSION}-x86_64-linux.tar.xz" + && curl --silent --show-error --location \ + "https://releases.nixos.org/nix/nix-${NIX_VERSION}/nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ + -o "nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ + && tar -xf "nix-${NIX_VERSION}-x86_64-linux.tar.xz" \ + && ln -s "nix-${NIX_VERSION}-x86_64-linux" nix \ + && rm -rf "nix-${NIX_VERSION}-x86_64-linux.tar.xz" # Ensure go bins are in the 'coder' user's path. Note that no go bins are # installed in this docker file, as they'd be mounted over by the persistent @@ -350,4 +350,4 @@ ENV GOPRIVATE="coder.com,cdr.dev,go.coder.com,github.com/cdr,github.com/coder" # Increase memory allocation to NodeJS ENV NODE_OPTIONS="--max-old-space-size=8192" -USER coder \ No newline at end of file +USER coder