Update migrations using UPDATE_SECRET in .env

I’m having a rather strange issue with this one (4.1.4 self-hosted). If I’m not using UPDATE_SECRET in the .env file, then going to http://ninja.url/update works just fine. However, if I enable UPDATE_SECRET, I run into a snag. Visiting http://ninja.url/update?secret=<string> returns the “Whoops. It looks like something went wrong.” page. But then trying again, the commands work and everything is fine.

A minor annoyance if manually updating, but in trying to get this part of the autoupdate script working, this causes wget to break out with

HTTP request sent, awaiting response... 400 Bad Request
Remote file does not exist -- broken link!!!

I’ve been pulling my hair out trying to sort this one, but it’s beyond me at this point. I defer to the masters for help.

Before I forget, here’s the laravel error that shows up when I get the error page in my browser (no error shows up when the initial attempt is with wget, however)

[2018-01-27 05:42:35] production.ERROR: Symfony\Component\HttpKernel\Exception\HttpException [400] : /var/www/ninja/bootstrap/cache/compiled.php [Line 2097] => Invalid secret: /update?secret=<value> {"context":"PHP","user_id":0,"account_id":0,"user_name":"","method":"GET","url":"http://myninja.url/update","previous":"http://myninja.url/update?secret=<secret_string>","user_agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.97 Safari/537.36 Vivaldi/1.94.1008.44","ip":"xxx.xxx.xxx.103","count":1,"is_console":"no","is_api":"no","db_server":"mysql"} []

Hmm… I’m not sure why it would fail and then work.

Is it possible it’s related to the specific secret value, have you tried using ‘1234’ (or something simple)

The value I’m using isn’t much more complicated than that. Just a 128-bit string of letters and numbers.

I haven’t been able to reproduce the problem.

Try adding this line of code:

dd(sprintf('.env secret: %s, request secret: %s', $password, request('secret')));

Here:

https://github.com/invoiceninja/invoiceninja/blob/master/app/Http/Controllers/AppController.php#L278

Still trying to work this one out, just haven’t had a whole lot of time to mess with it. At this point I’m not sure if it’s something in the app, or just my testing methodology (manually altering version.txt to force an update). Once the new version drops we’ll see how that goes.

Have you tried adding the code I suggested.

Note: it will prevent the update but may provide more clues as to why it’s failing.

I’m assuming that goes after the specified line?

Here’s the wget output with the code added in.


user@host:~$ wget --spider 'http://myninja.url:port/update?secret=12345678'
Spider mode enabled. Check if remote file exists.
--2018-02-04 01:58:26--  http://myninja.url:port/update?secret=12345678
Resolving myninja.url (myninja.url)... xxx.xxx.xxx.xxx
Connecting to myninja.url (myninja.url)|xxx.xxx.xxx.xxx|:port... connected.
HTTP request sent, awaiting response... 500 Internal Server Error
--2018-02-04 01:58:27--  (try: 2)  http://myninja.url:port/update?secret=12345678
Connecting to myninja.url (myninja.url)|xxx.xxx.xxx.xxx|:port... connected.
HTTP request sent, awaiting response... 500 Internal Server Error
Remote file does not exist -- broken link!!!

Here it is after I remove the code and run it the first time.


user@host:~$ wget --spider 'http://myninja.url:port/update?secret=12345678'
Spider mode enabled. Check if remote file exists.
--2018-02-04 01:59:14--  http://myninja.url:port/update?secret=12345678
Resolving myninja.url (myninja.url)... xxx.xxx.xxx.xxx
Connecting to myninja.url (myninja.url)|xxx.xxx.xxx.xxx|:port... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://myninja.url:port/update [following]
Spider mode enabled. Check if remote file exists.
--2018-02-04 01:59:14--  http://myninja.url:port/update
Connecting to myninja.url (myninja.url)|xxx.xxx.xxx.xxx|:port... connected.
HTTP request sent, awaiting response... 400 Bad Request
Remote file does not exist -- broken link!!!

Then when I run it again immediately afterward, it works, resulting in


user@host:~$ wget --spider 'http://myninja.url:port/update?secret=12345678'
Spider mode enabled. Check if remote file exists.
--2018-02-04 01:59:20--  http://myninja.url:port/update?secret=12345678
Resolving myninja.url (myninja.url)... xxx.xxx.xxx.xxx
Connecting to myninja.url (myninja.url)|xxx.xxx.xxx.xxx|:port... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://myninja.url [following]
Spider mode enabled. Check if remote file exists.
--2018-02-04 01:59:23--  http://myninja.url/
Connecting to myninja.url (myninja.url)|xxx.xxx.xxx.xxx|:port... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://myninja.url/login [following]
Spider mode enabled. Check if remote file exists.
--2018-02-04 01:59:23--  http://myninja.url/login
Connecting to myninja.url (myninja.url)|xxx.xxx.xxx.xxx|:port... connected.
HTTP request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Remote file exists and could contain further links,
but recursion is disabled -- not retrieving.

None of the wget attempts leave errors in laravel-error.log

Going to the URL in a browser with the added code gets “Whoops. Looks like something went wrong.”, but with two separate boxes on the page saying that. laravel-error.log shows


[2018-02-04 07:09:22] production.ERROR: ***Symfony\Component\Debug\Exception\FatalThrowableError*** [0] : /var/www/ninja/app/Http/Controllers/AppController.php [Line 279] => Parse error: syntax error, unexpected 'secret' (T_STRING), expecting ',' or ')'  {"context":"PHP","user_id":0,"account_id":0,"user_name":"","method":"GET","url":"http://myninja.url:port/update","previous":"http://myninja.url:port","user_agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.121 Safari/537.36 Vivaldi/1.95.1077.41","ip":"xxx.xxx.xxx.xxx","count":1,"is_console":"no","is_api":"no","db_server":"mysql"} []
[2018-02-04 07:09:22] production.ERROR: ***Symfony\Component\Debug\Exception\FatalThrowableError*** [0] : /var/www/ninja/app/Http/Controllers/AppController.php [Line 279] => Parse error: syntax error, unexpected identifier (T_STRING), expecting ',' or ')'  {"context":"PHP","user_id":0,"account_id":0,"user_name":"","method":"GET","url":"http://myninja.url:port/update","previous":"http://myninja.url:port","user_agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.121 Safari/537.36 Vivaldi/1.95.1077.41","ip":"xxx.xxx.xxx.xxx","count":2,"is_console":"no","is_api":"no","db_server":"mysql"} []

Removing the code once again and trying with a browser results in the 400 error mentioned above, before finally going through successfully the second time.

I think the quotes in the code were broken by the forum, please try copying it again.

Also, it’d be helpful to see the output the first time it’s run.

wget seems to return the same thing as if it had worked, while using a browser displays ".env secret: 12345678, request secret: "

Both cases still set version.txt to the current version

It looks like the request secret is blank, maybe the server configuration is causing the field to not be passed?

It got passed. I just replaced the actual secret with 12345678 instead of the actual update key it was displaying.

Nvm, wasn’t looking at the right part of the code.

But it’s odd that it doesn’t work on the initial try, but immediately re-trying works just fine.

Yeah, definitely odd. Not sure why…

So I think I’ve narrowed down the where and the when, just not sure as to the why.

Running wget --spider 'http://ninja.url/update?secret=12345' starts out the same way in both instances. But after the first 302 response, things get wonky.

On the first attempt (that doesn’t work), I get redirected to http://ninja.url/update, which is when it errors out with a 400 response and says the link is broken.

On the second go-around, I get redirected to http://ninja.url, which kicks off another 302 redirect to http://ninja.url/login, then finally to a 200 response when the login page is served after the artisan commands have run.

I’ll be the first to admit that I’m completely out of my depth on this one. Were it an issue where it just flat out refuses to work, that would be one thing. But since it works fine when the exact same request is made a second time, I’m not really sure how to diagnose that.

I’m sorry, I’m not sure… no one else has reported the issue which makes me think it’s related to the web server configuration.

So just to rule out a problem with my specific configuration (Ubuntu Server + Apache), I tried a couple different installations.

• Installed IN on my Debian desktop under Apache, same issue.
• Installed under a bare Debian netinst with Apache and nothing else. Same issue.
• Another bare Debian netinst, this time with nginx instead of Apache. Same issue.

I even set UPDATE_SECRET to a simple 1234, still no luck.

Aside from the desktop install, the other two Debian installs were as bare as could be. Nothing other than ssh and all the dependencies for Laravel/InvoiceNinja. Since the same thing happened with nginx, I’m sure it’s not related to any configuration issues in Apache.

If anyone in the community happens to be using UPDATE_SECRET and they’re not having this issue, I’d love to see what the differences are between our installs.