The current top answer is wrong on multiple levels.
First, it misses the main issue, which is simply that 'verify' does not verify chains of certificates in a single file in this way. Proof:
$ cp /etc/ssl/certs/Certigna_Root_CA.pem /tmp/poc.pem
$ echo "unverifiable garbage" >> /tmp/poc.pem
$ openssl verify /tmp/poc.pem
/tmp/poc.pem: OK
Thus, of the 2 provided orderings in the original question, only the one which has a root certificate at the beginning will report "OK", because that invocation simply checks the root certificate alone, and that is already trusted by the system.
On the subject of ordering certificates, the order as specified in the standard ("The sender's certificate MUST come first in the list.") and that of nginx ("The server certificate must appear before the chained certificates in the combined file") match each other. This corresponds to the OP's first attempt using cat.
The actually correct answer is in the email-thread which was linked by the OP. I'll quote it here:
on the command line, things are unnecessarily difficult.
Here is what you need to do:
Split the chain file into one file per certificate, noting the order
For each certificate starting with the one above root:
2.1 Concatenate all the previous certificates and the root certificate
to one temporary file (This example is for when you are checking the
third certifate from the bottom, having already checked cert1.pem and
cert2.pem
Unix: cat cert2.pem cert1.pem root.pem > cert2-chain.pem
Windows: copy /A cert1.pem+cert1.pem+root.pem cert2-chain.pem /A
2.2 Run this command
openssl verify -CAfile cert2-chain.pem cert3.pem
2.3 If this is OK, proceed to the next one (cert4.pem in this case)
Thus for the first round through the commands would be
Unix: cat root.pem > root-chain.pem
Windows: copy /A root.pem root-chain.pem
Both: openssl verify -CAfile root-chain.pem cert1.pem
And the second round would be
Unix: cat cert1.pem root.pem > cert1-chain.pem
Windows: copy /A cert1.pem+root.pem cert1-chain.pem
Both: openssl verify -CAfile cert1-chain.pem cert2.pem
Etc.
Further notes:
- Step 1 (splitting the file) may be automated like so:
csplit -f cert- $file '/-----BEGIN CERTIFICATE-----/' '{*}'
openssl verify takes information about trust from your system (e.g. /etc/ssl/certs/) also, so if you really want to make sure that you're verifying correctly your invocation should be something like openssl verify -verbose -x509_strict -CAfile upto-cert-02 -CAPath nosuchdir cert-01 (where nosuchdir is a non-existing path, and upto-cert-02 is the concatenation of files cert-nn to certt02)