supernova32

supernova32

Plug.Static is unable to serve files in production

Hi everyone,

I have been banging my head against a wall for the last couple of days because of a really weird problem I’m having in production.

I have a very simple Phoenix app that lets an admin user upload an image when creating a “note”. I’m using arc and arc-ecto to handle the file uploads. Everything works great in development. I’m able to upload the images without issues, and I can see them on the “notes” page.

However, when the app is running in production, I am able to upload the images without errors, but Phoenix is giving me a 404 when trying to fetch the images.

I already added the Plug.Static declaration to may endpoint.ex file, which is why I am able to see the images in dev, but no matter what I try in production, I always get a 404.

I have this in my endpoint.ex file. I already tried replacing Path.expand("./uploads") with the full path of where the files are when in production, and no luck.

plug Plug.Static,
    at: "/uploads",
    from: Path.expand("./uploads/"),
    gzip: false

I know Elixir has access to this folder in production, because after uploading the images, they are there.

I’m using Distillery to create the release for production, and I’m deploying the app as a Docker image using docker-compose. I already made sure that the destination of the uploaded files is mounted as a volume on the Docker image, so that they don’t get destroyed after each deploy.

What could possibly be happening here?

I’m really close to just giving up trying to get Plug.Static to work in prod, and just Base64 encode the images and inlining them in the HTML file.

Any help, or guidance you can give me is greatly appreciated!

Marked As Solved

supernova32

supernova32

I gave up on trying to get it to work. I decided to just Base64 encode the image and send it inline within the HTML data. This is working perfectly in production now, which means it is probably not an issue with the OS or file system.

Once the app gets proper usage, I’ll be redoing most of the infrastructure, so images will be stored on S3, which will make this problem irrelevant anyhow.

Anyways if somebody comes across this problem in the future, let me know. I can revisit it then, and we can work on it together.

Also Liked

wojtekmach

wojtekmach

Hex Core Team

See this excerpt from the docs

The preferred form is to use :from with an atom or tuple, since it will make your application independent from the starting directory. For example, if you pass:

    plug Plug.Static, from: "priv/app/path"

Plug.Static will be unable to serve assets if you build releases or if you change the current directory. Instead do:

    plug Plug.Static, from: {:app_name, "priv/app/path"}

have you tried it with tuple?

thinkingcat

thinkingcat

I spent the entire afternoon and half a morning trying to fix this issue as well.

Turns out that in production (with Gigalixir) Path.expand goes to app/uploads which @supernova32 is aware of, but the upload goes to the same place that it did (I’m using Waffle/the updated Arc library)

The simple solution is to simply hardcode the directory from which we are serving the assets from.

i.e.

  plug(Plug.Static,
    at: "/uploads",
    from: "./uploads",
    gzip: false
  )

instead of

from: Path.expand("./uploads/"),

I haven’t tested it again in a dev environment but hopefully it should help someone else save some time, because this is a very simple fix that shouldn’t have taken me, or anyone else, more than 15 minutes :frowning: .

NobbZ

NobbZ

WHat does Path.expand("./uploads/") return? Is it as expected and really the folder you have configured as target for copying the uploaded files to? relative pathes can be mean at times, especially if one isn’t careful or conscious about the actual working directory.

Sadly you haven’t told us how you are starting your application… That could give some hints about the actual working directory.

Where Next?

Popular in Questions Top

hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
JeremM34
Hello, how can I check the Phoenix version ? Thanks !
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
vrod
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors: [WARN] - (starship::utils): Executing command ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
openscript
Hello! Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New

Other popular topics Top

WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
pmjoe
I have a relationship of love and hate with Elixir. Lots of things are just absolutely right, but there are some things that are kind of ...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
KronicDeth
Elixir plugin for JetBrain’s IntelliJ Platform (including Rubymine) This is a plugin that adds support for Elixir to JetBrains IntelliJ...
289 36352 110
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
AstonJ
We’ve put together this wiki for Phoenix LiveView - please feel free to add any info you feel is worth including. What is Phoenix LiveV...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54120 245
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement