Skip to content

Conversation

mikeland73
Copy link
Contributor

@mikeland73 mikeland73 commented Sep 10, 2022

Summary

Implements static nginx planner for both shell and build commands. The strategy is a bit different for each:

  • For both shell and build nginx is installed as a package. (Maybe we should consider using services for build instead?)
  • For shell, we compile with a few flags to ensure nginx can run with limited commands. Some inspiration borrowed from here. It creates a script wrapper to ensure flags are correct.
  • For build, it's a bit more straightforward (see readme for more details). We ensure we create the nginx user following inspiration from nginx docs (we may want to follow more of that doc in the future)
  • Marking this as experimental, since it will probably change.

How was it tested?

  • unit tests
  • devbox shell followed by calling nginx-shell
  • devbox build, followed by docker run -p 80:80

@LucilleH
Copy link
Collaborator

I'm not sure if we need to support nginx in a shell. I do also have a working version with just some customization on devbox.json

@mikeland73
Copy link
Contributor Author

@LucilleH this PR is build only. But I think I can make it work in shell

@Lagoja Lagoja linked an issue Sep 13, 2022 that may be closed by this pull request
@mikeland73 mikeland73 marked this pull request as ready for review September 14, 2022 23:27
@mikeland73 mikeland73 changed the title [nginx][WIP] Add nginx static file planner [nginx]Add nginx static file planner DEV-1147 Sep 14, 2022
@mikeland73
Copy link
Contributor Author

@LucilleH @loreto now ready for review and supports build and shell.

@LucilleH
Copy link
Collaborator

LucilleH commented Sep 15, 2022

I don't know if this is the right way to solve it. I pulled the branch and tested with Docusaurus and it doesn't serve as expected (broken pages w no proper css files, etc). I might have misconfigured it perhaps.

But more importantly, do we want to use Nix services? We can generalize it to support services in general, nginx, Apache, LAMP stack, etc. See https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nginx.nix

Thoughts?

with a few options. If you want to see what this wrapper does, use `cat $(which shell-nginx)`

In shell everything is local so you should avoid pointing to assets or files outside
the directory because the nix shell might not have access. For example your root
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which directory?

}

func (p *Planner) GetPlan(srcDir string) *plansdk.Plan {
fmt.Println(srcDir)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intentional?

nginx -c /app/%[1]s -g 'daemon off;'
`)

const customNginxDefintion = `
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const customNginxDefintion = `
const customNginxDefinition = `

// These definitions are only used in shell. Since nix is lazy, it won't
// actually build them at all if they are not used.
Definitions: []string{
customNginxDefintion,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
customNginxDefintion,
customNginxDefinition,

Comment on lines 19 to 26
// TODO: Plan currently has a bunch of fields that it should not export.
// Two reasons why we need this right now:
// 1/ So that individual planners can use the fields
// 2/ So that we print them out correctly in `devbox plan`
//
// (1) can be solved by using a WithOption pattern, (e.g. NewPlan(..., WithWelcomeMessage(...)))
// (2) can be solved by using a custom JSON marshaler.
type Plan struct {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's put an empty line between this comment and Plan so it doesn't show up in godocs.

@@ -116,6 +108,10 @@ func (p *Plan) WithError(err error) *Plan {
return p
}

func (p *Plan) ShellAndDevPackages() []string {
return pkgslice.Unique(append(p.DevPackages, p.ShellPackages...))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You probably want to copy to a new slice here, otherwise the returned slice and DevPackages will share the same backing array.

DevPackages []string `cue:"[...string]" json:"dev_packages"`

// ShellPackages are only available in the shell environment.
ShellPackages []string `cue:"[...string]" json:"shell_packages"`
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does including shell packages in the dev environment add a lot of extra stuff?

I think trying to keep a single set of packages would be more reliable. If the shell has extra packages, then it means your dev environment no longer matches what gets built.

Comment on lines 40 to 42
{{ if .ShellWelcomeMessage }}
echo "{{ .ShellWelcomeMessage }}"
{{- end }}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know we also echo another message in this hook, but we should probably move them to the shellrc template. This hook will also run with non-interactive shells, so devbox run 'some-command' or devbox shell < myscript.sh will end up printing these messages.

@mikeland73
Copy link
Contributor Author

@LucilleH @gcurtis reimplemented using same nginx for shell and build.

The user needs to add some config options when running in shell. For simplicity I generate the file and tell them to include it in the welcome message. It's not a fantastic experience, but it prevents us from having two different nginx builds.

We could try to automate the nginx.conf construction, but I feel like that could be really error prone.

Ideally we can add the options in the command line call but I'm not sure that's possible.

@LucilleH
Copy link
Collaborator

Tested locally, when running shell-nginx I got the following error:

Starting nginx with command:
nginx -p . -c nginx.conf -e /tmp/error.log -g "pid /tmp/mynginx.pid;daemon off;"
nginx: [warn] the "user" directive makes sense only if the master process runs with super-user privileges, ignored in ./nginx.conf:1
nginx: [emerg] open() "./mime.types" failed (2: No such file or directory) in ./nginx.conf:4

}

func AllFiles() []string {
return []string{"."}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh this is nice. Should've done this earlier

@LucilleH
Copy link
Collaborator

Doing devbox build and docker run, I got the following error:

docker run -p 80:80 --expose 80 -ti devbox
Starting nginx with command "nginx -c /app/nginx.conf -g daemon off;"
nginx: [emerg] open() "/app/mime.types" failed (2: No such file or directory) in /app/nginx.conf:4

It was working in the previous version 🤔

mkdir -p /var/cache/nginx/client_body && \
mkdir -p /var/log/nginx/ && \
PKG_PATH=$(readlink -f $(which nginx) | sed -r "s/\/bin\/nginx//g") && \
ln -s /app/%[1]s $PKG_PATH/conf/devbox-%[1]s && \
Copy link
Collaborator

@LucilleH LucilleH Sep 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wow ok. I'm still getting nginx: [emerg] open() "./mime.types" failed (2: No such file or directory) in ./nginx.conf:4

nginx fails to start when the temporary directories in
shell-helper-nginx.conf don't exist yet. Specifically, the `cache`
subdirectory needs to be created under the temp directory. To fix this:

1. Use os.TempDir() to ensure we use the OS-specific temporary
   directory (which on macOS isn't `/tmp`).
2. Don't use a `cache` subdirectory so we don't need to worry about the
   directory existing.
@gcurtis
Copy link
Collaborator

gcurtis commented Sep 19, 2022

@mikeland86 I resolved the conflicts so I could test things out. Is it okay if I push them here?

@mikeland73
Copy link
Contributor Author

@gcurtis go for it

Copy link
Collaborator

@gcurtis gcurtis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I was able to run both a shell and a built image. I think this is a good first iteration.

@mikeland73 mikeland73 merged commit fc9c787 into main Sep 19, 2022
@mikeland73 mikeland73 deleted the landau/nginx-support branch September 19, 2022 22:22
mikeland73 added a commit that referenced this pull request Sep 23, 2022
## Summary

This is stacked on #105. Please
review that one first.

Adds basic pip support. 

* Uses requirements.txt for detection.
* Uses venv for shell
* Uses venv + pex for build

Does not yet libraries with native extensions like `pandas` but there's
a plan for that.

## How was it tested?

* `devbox shell`. 
* `devbox build`
* Unit tests

Co-authored-by: Greg Curtis <greg.curtis@jetpack.io>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Language Support: Nginx + Static Files
3 participants