Managing certificates

I’ve been reading the TrueNAS 24.10 documentation regarding certificate management in TrueNAS and have questions about it.

Currently, I have a wildcard certificate for my domain that I get from lets encrypt and it needs to be refreshed every 90 days or so. I have the certbot running in a VM using a DNS authenticator with Cloudflare which keeps my wildcard cert updated and I have to manually update the lets encrypt cert that I’ve installed on my TrueNAS hosts.

I’d like to move this from the VM and have TrueNAS handle all this and keep the cert used by the UI up to date but, from reading the documentation, it is not entirely clear that TrueNAS will do that. I’ve added my Cloudflare DNS authenticator into TrueNAS but I’m not sure how it is used. Do I need to install a CSR to TrueNAS and if I install the CSR, will it use certbot to create and fetch the cert from lets encrypt? Will TrueNAS update the cert within 90 days automatically? Appreciate your help.

thanks
John

All about certs in TrueNAS:

Specifically, how the built-in facility works:

I think it uses acme.sh rather than certbot, but that’s an implementation detail you shouldn’t need to worry about.

Edit: Another option would be to keep using the wildcard cert you’ve been using, and use my script to deploy that script to TrueNAS. For information about that script, see:

and

2 Likes

Thanks Dan, I’m going to look at your script and most likely use it to import it into my TrueNAS instances.

Great. Let me know how it works, if you have problems, and/or if the docs need to be clearer.

FYI: ACME includes a TrueNAS deployment. Looks like the documentation in the readme is for CORE (documentation still references ‘jails’) but they have deployments for using the REST and the Websocket tested on 24.10.

deployhooks · acmesh-official/acme.sh Wiki · GitHub

Well, acme.sh does–ACME is the protocol used to request and receive the cert. I don’t document that method because I’m not too familiar with it; they don’t document it because reasons.

I think my babble-fish is on the fritz. …say again (I linked to the documentation)?

EDIT:
I’ve read your reply several times now and I still don’t understand it, but I’ll post the “usage command” listed in the readme:

acme.sh --insecure --deploy -d truenas.example.com --deploy-hook
truenas_ws

Here is also a link to the websocket deploy script.

I very quickly looked at the other TrueNAS deploy script but it’s a bit garbled. The truenas_ws.sh looks better so, I’d probably start with that one.

1 Like

I’ll take your word for it; it definitely isn’t listed on the page you linked describing the deploy hooks.

Neither I nor Ctrl-F find any mention of the truenas_ws script on the page you linked.

I’m not sure what there is to not understand, unless you don’t get the distinction between ACME and acme.sh. The former is a protocol, initially developed by Let’s Encrypt and now used by a number of certificate authorities, to allow users to request and receive trusted certificates in an automated fashion.[1] The latter is one client implementation to that protocol. It self-describes as a shell-only implementation, and that’s largely true with respect to acme.sh itself, but it isn’t true of all the deployment scripts, specifically the truenas_ws one–that one requires just as much python as mine.[2]

If you find this:

  _ui_certificate_id=$(printf "%s" "$_ws_response" | jq -r '."ui_certificate"."id"')

easier to follow than this:

    cert_id = cert["id"]

I guess that’s up to you. Obviously you should do whatever best meets your needs.


  1. It’s fully documented in RFC8555 ↩︎

  2. Well, almost as much–I don’t believe truenas_ws.sh requires Python’s OpenSSL library, because it doesn’t do anything to validate that the cert and the private key match. ↩︎

1 Like

@dan I’m having trouble using deploy_truenas.py on my NAS which is currently running fangtooth 25.04. I read in another post that you were having trouble with the script and the 25.04 API. I’ve skipped the acme.sh altogether as I have a copy of my wild card cert.pem and fullchain.pem on the NAS and just need to import them. So when I use the script, I get this:

2025-04-02 09:07:15,768 - root - INFO - ✅ Certificate and private key match.
2025-04-02 09:07:15,773 - websocket - INFO - Websocket connected
2025-04-02 09:07:18,169 - root - CRITICAL - Failed to authenticate!

You mentioned in the other post that 25.04 needs to see the host FQDN in the cert. My cert is a wildcard using *.mydomain.org. Is this a problem with 25.04? Is the current script I download have your 25.04 modifications?

thanks
John

I don’t know what to say other than: “yes it is”?

  1. Deploy the cert on TrueNAS Core Server

    If you run acme.sh on a system other than the TrueNAS server then you will need to set the DEPLOY_TRUENAS_HOSTNAME to the IP or Hostname of the TrueNAS server. If the setting “Web Interface HTTP → HTTPS-Redirect” in the TrueNAS web interface is checked then DEPLOY_TRUENAS_SCHEME will be set to https by default.

acme.sh --insecure --deploy -d truenas.example.com --deploy-hook truenas

You use the deploy-hook you want/need. They are all in the deploy directory.

Protocol v script? Wait. What does that have to do with anything (how did the conversation switch to that)? I mean, of course I understand what a protocol is but I don’t understand why you’re asking/talking to me about it.

I honestly don’t know what you mean by readability. …both are ‘easy’?

The first statement is assigning a variable from the result of a (piped) command(s).

The second is assigning a variable to the value of an “array element”.

The statements are fundamentally different in nature (partly because they are two different languages, and each have different methods) but I suppose I can sort of answer to the common thread to both.

Speaking about “programming syntax/method reliability”. On the face, the first one, is typically “less reliable” because there more conditions where _ui_certificate_id could be not correctly set (like: jq isn’t on the system or…) so, you’d just need to validate/assert the variable gets assigned properly. In programming you typically employ the “try/catch” method if you can or just use a simple “assert” type function (depends on the language you use).

So you’d use:

MyVariable=$(command)
if assert $MyVariable; then

Most programmers will do these types of checks automatically (becomes second nature). However, it’s worth mentioning that some people try to crunch-down syntax because they have this weird misconception about number of lines being better but for the most part, it’s better to be more descriptive.

In C you get into situations where it’s better to crunch your syntax down into short one-liners (like when using pre-increment vs post-increment) and I think that sort of made people think that crunching down syntax into one liners is better in all languages but in reality, C programmers were/are/can employing different tools to different tasks and some area very elegant. But I certainly do not see the first example you gave as unnecessary crunching (I would have done it the same way) but I would have verified jq exists and _ui_certificate_id is valid before it’s used.

The second method about assigning the variable to a list element is more general (broad) depending how cert is defined but can be just as ‘unreliable’ depending on the programmer. For example if cert is a struct/class/object then a programmer should typically build these validations into the getters and setterts. …this also leads to a very interesting programming problem which I don’t think you’re actually asking or care about so I’ll leave that one alone.

I guess, I’m not really sure what your point is about readability, but those two statements/examples are sort of apples and oranges, and both are readable.

However, generally speaking (if you’re truly wondering about programming methodology to improve your script or something like that), if you want to learn programming, I highly recommend: Structure and Interpretation of Computer Programs (SICP). Very good book/class.

Why do you need a python lib to verify a cert? Isn’t the command something like:

openssl x509 -in <CERT> -text -noout

But?! Why would the deploy script (truenas_ws.sh, for example) need to verify the cert at all?

Why do you keep switching topics (which is very frustrating!)? I mean I don’t understand the programming syntax/methods sidebar or the protocol sidebar or a cert verification method in a subscript sidebar.

I’m not following this. I was asking @dan about the authentication failure with truenas_deploy.py on a 25.05 deployment.

John, Sorry, I was getting confused with all the messaging. I’ve looked over the document link you sent and that looks helpful. I did not see that before. I could not get Dan’s script to work with 25.04, not sure why it fails authentication. I’ve already installed my wildcard cert manually so and was testing his script to see if I could reinstall it with the script but, I get authentication failure after:

result=c.call("auth.login_with_api_key", API_KEY)

Dan mention in another post that he had problems with 25.04 as it seems to have tightened up security I guess. It always requires strict certificate validation with the api calls require the connect fqdn to match the CN in the cert used by TrueNAS. Since I installed my cert manually prior to testing the script, everything should match so, not sure why the call is failing to Authenticate. I’ve got a valid API Key that I generated on the 25.04 machine.

Hey jjrushford,
Yeah, I’m not really following that well either. I was just trying to give a link to the acme tools so you can possibly “get” and “deploy” a cert with one command. I’m a bit more programming heavy than I am with other aspects so I could be way off… I dunno. *shrug*

Let’s wait to see what dan says about that error because I’m a bit confused (I was thinking you can use the acme tools but maybe not). I’ll help if I can though.

I’m already using the acme tools on a FreeBSD VM, certbot pkg, to manage my lets encrypt cert and at this point I want to find a way to import that cert without having to use the UI manually every 3 months. However, I could eventually move it from the VM to TrueNAS using the acme tools there.

Well, (another forewarning) I probably won’t be able to help much with the TrueNAS SCALE API calls because I’m still rocking with TrueNAS CORE but I’ll certainly try to help if I can.

1 Like

No, it isn’t, and the text you quote doesn’t indicate to the contrary. The truenas deploy script is not the truenas_ws deploy script. They do different things and have different capabilities (for one thing, the truenas_ws has no ability to connect to a remote host). And that’s presumably why the paragraph discussing it explicitly only documents the script for CORE (which is the one without _ws in the file name).

You don’t see any value in the script that deploys a certificate validating that the cert and key being used match? Which the openssl invocation you give does’t do, BTW. Because that seems to me to be a useful check for the script to perform–don’t deploy data that you know to be garbage. It avoids problems like the one noted here: KeyPairMismatchException: private and public keys don't match when uploading to AWS Load Balancer - Help - Let's Encrypt Community Support

If you’re saying the one script is easier to follow (which is what I understand by your saying that the other–i.e., mine–is “a bit garbled”), then comparison of the relevant code seems relevant. Your lengthy discussion of what you understand the two snippets given to do is your own.

The “protocol sidebar” is because you claimed ACME has a deployment script. It doesn’t. ACME is a protocol. acme.sh has a deployment script. They’re two completely different things that happen to have similar names.

I wanted to be accurate. The truenas_ws deployment script needs just as much Python (to which you’d expressed an aversion in another thread) as does my script, with the exception of Python’s OpenSSL library, which is required by mine for the reasons stated, and doesn’t appear to be required by truenas_ws because it doesn’t do this.

@dan, I was hacking on deploy_truenas.py and got it working. At first, I hadn’t noticed that my API Key got revoked, too many authentication failures I guess. Anyway, I read that the URI for 25.04 is now /api/current. I changed the URI in the script from the 24.10 URI, /websocket.

Anyway, it’s now working for me. Thanks for the script.

So, a few questions:

  • Which version of TrueNAS are you using (I’m guessing from the rest of your post it’s 25.04-RC1)?
  • What are the contents of deploy_config (naturally you’ll want to mask the API key, and connect_host if you like)?
  • Do you have any notifications in the UI about the API key being revoked?

Both work in 25.04, but I presume /api/current will go away in the future.

If the key gets passed over an insecure channel (e.g., if you try to use it via ws:// rather than wss://), 25.04 will automatically revoke it. That’s likely what happened IMO.

Yeah, originally I had protocol = ws, while troubleshooting, I later changed it to wss but did not notice my key was revoked. So, /api/current is temporary?

Nice job on the script though, I like it. It imports the cert and automatically switches and restarts the UI to use it! This will work out well for me!