Error in systemd only {:error, {:ssl, {'no such file or directory', 'ssl.app'}}}

Hello

I can start the app locally as: MIX_ENV=dev iex -S mix phx.server without any issue, but if I start the app in a systemd, I got error:

Could not start Hex. Try fetching a new version with "mix local.hex" or uninstalling it with "mix archive.uninstall hex.ez"
$ bash[38908]: ** (MatchError) no match of right hand side value: {:error, {:ssl, {'no such file or directory', 'ssl.app'}}}

Here is my systemd file:

[Unit]
Description=phoenix server
Requires=network.target

[Service]
Type=simple
User=samir
Group=samir
Environment=PATH=/home/samir/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH
Environment=MIX_ENV=dev "PORT=4000"
WorkingDirectory=/home/samir/projects/ngspice-server/
ExecStart=/usr/bin/bash -lc '/home/samir/.asdf/shims/iex -S mix phx.server'
TimeoutSec=30
RestartSec=15s
Restart=always

[Install]
WantedBy=multi-user.target

But I start it locally at terminal successfully using the same command in systemd:

/usr/bin/bash -lc '/home/samir/.asdf/shims/iex -S mix phx.server'

Any idea?

You probably need to populate the environment with more info to make systemd able to find all the stuff, especially as systemd will not load your users bashrc

Why on the Earth you want to do this in the first place? Build a release and start the release. In any case you are not suppose to have iex nor mix in production.

1 Like

This is not for production, this is for production on my laptop, I find it very useful to start the server this way rather than start it my self each time.

Its not meant for production, but for production instead?

I think you mean development, as you try starting the server using MIX_ENV=dev

You won’t be able to use the console started through iex anyway, restarting needs to be done through systemctl --user restart your-app-in-development.service… Why not just C-g q RET to exit current iex and then iex -S mix phx.server?

Using a systemd service seems to be even more complicated than doing it the way that everyone else uses…

Ah, yes I mean its for development on my laptop, Its ok not to use the console most of cases for my project.
I preferred systemd as my phoenix project is a dependency for my rails app. I don’t like to dedicate a terminal each time when I boot my laptop and start the phoenix each time as its a sub project.

I am not advocating to start it every time from the command line. I am positive that mix release and bin/my_app start would be drastically easier.

Thanks, I will try so.

I just tried to start the release as:

_build/dev/rel/ngspice_proxy/bin/ngspice_proxy start

but I got error:

[info] Application cortex exited: exited in: Cortex.Application.start(:normal, [])
    ** (EXIT) an exception was raised:
        ** (UndefinedFunctionError) function Mix.env/0 is undefined (module Mix is not available)
            Mix.env()
            (cortex 0.5.0) lib/cortex/application.ex:12: Cortex.Application.start/2
            (kernel 6.5.2) application_master.erl:277: :application_master.start_it_old/4
{"Kernel pid terminated",application_controller,"{application_start_failure,cortex,{bad_return,{{'Elixir.Cortex.Application',start,[normal,[]]},{'EXIT',{undef,[{'Elixir.Mix',env,[],[]},{'Elixir.Cortex.Application',start,2,[{file,\"lib/cortex/application.ex\"},{line,12}]},{application_master,start_it_old,4,[{file,\"application_master.erl\"},{line,277}]}]}}}}}"}
Kernel pid terminated (application_controller) ({application_start_failure,cortex,{bad_return,{{'Elixir.Cortex.Application',start,[normal,[]]},{'EXIT',{undef,[{'Elixir.Mix',env,[],[]},{'Elixir.Cortex.

But how-come I it works fine using mix phx.server ??

The reason is that Mix only exists when you are running your app outside of an release, in the source code folder. It is not itself packaged in the release.

This means that you can still rely on it existing at compile time and release building time, but not when starting a release that has been built.

Depending on where the call to Mix.env is you might:

  • Add configuration in your Application.config files which indicates what kind of environment you are running in.
  • Read it out at compile-time and store it somewhere, using for instance
def YourModule do

  @compiled_with_env Mix.env()

  # ...

  def your_function() do
    # ...
   if @compiled_with_env == :dev do
        # ...
    end
    # ...
  end
  # ...
end
  • Not depend on Mix at all and decide in some other way the context in which the release is running, like reading out environment variables or other kinds of configuration.
1 Like

Or, alternatively (although extremely not recommended) add mix application to release.