Using a Self-Signed Certificate

Ktor allows you to create and use self-signed certificates for serving HTTPS or HTTP/2 requests.

This function is defined in the method io.ktor.network.tls.certificates.generateCertificate in the artifact io.ktor:ktor-network-tls:$ktor_version.

dependencies { implementation "io.ktor:ktor-network-tls:$ktor_version"}

dependencies { implementation("io.ktor:ktor-network-tls:$ktor_version")}

<project> … <dependencies> <dependency> <groupId>io.ktor</groupId> <artifactId>ktor-network-tls</artifactId> <version>${ktor.version}</version> <scope>compile</scope> </dependency> </dependencies></project>

Table of contents:

To create a self-signed certificate using Ktor, you have to call the generateCertificate function.

  1. io.ktor.network.tls.certificates.generateCertificate(File("mycert.jks"))

Since Ktor requires the certificate when it starts, you have to create the certificate before starting the server.

Create the certificate using gradle

One possible option is to execute the main class generating the certificate before actually running the server:

CertificateGenerator.kt

You can declare a class with a main method that only generates the certificate when it doesn’t exist:

  1. package io.ktor.samples.http2
  2. import io.ktor.network.tls.certificates.generateCertificate
  3. import java.io.File
  4. object CertificateGenerator {
  5. @JvmStatic
  6. fun main(args: Array<String>) {
  7. val jksFile = File("build/temporary.jks").apply {
  8. parentFile.mkdirs()
  9. }
  10. if (!jksFile.exists()) {
  11. generateCertificate(jksFile) // Generates the certificate
  12. }
  13. }
  14. }

build.gradle

In your build.gradle file you can make the run task to depend on a generateJks task that executes the mainclass generating the certificate. For example:

  1. task generateJks(type: JavaExec, dependsOn: 'classes') {
  2. classpath = sourceSets.main.runtimeClasspath
  3. main = 'io.ktor.samples.http2.CertificateGenerator'
  4. }
  5. getTasksByName("run", false).first().dependsOn('generateJks')

The HOCON application.conf configuration file

When creating your HOCON configuration file, you have to add the ktor.deployment.sslPort, and the ktor.security.sslproperties to define the ssl port and the keyStore:

resources/application.conf:

  1. ktor {
  2. deployment {
  3. port = 8080
  4. sslPort = 8443
  5. watch = [ http2 ]
  6. }
  7. application {
  8. modules = [ io.ktor.samples.http2.Http2ApplicationKt.main ]
  9. }
  10. security {
  11. ssl {
  12. keyStore = build/temporary.jks
  13. keyAlias = mykey
  14. keyStorePassword = changeit
  15. privateKeyPassword = changeit
  16. }
  17. }
  18. }

Ktor normal module

After that you can just write a normal plain Ktor module:

Module.kt

  1. package io.ktor.samples.http2
  2. import io.ktor.application.*
  3. import io.ktor.features.*
  4. import io.ktor.http.*
  5. import io.ktor.response.*
  6. import io.ktor.routing.*
  7. import io.ktor.util.*
  8. import java.io.*
  9. fun Application.main() {
  10. install(DefaultHeaders)
  11. install(CallLogging)
  12. install(Routing) {
  13. get("/") {
  14. call.push("/style.css")
  15. call.respondText("""
  16. <!DOCTYPE html>
  17. <html>
  18. <head>
  19. <link rel="stylesheet" type="text/css" href="/style.css">
  20. </head>
  21. <body>
  22. <h1>Hello, World!</h1>
  23. </body>
  24. </html>
  25. """.trimIndent(), contentType = ContentType.Text.Html)
  26. }
  27. get("/style.css") {
  28. call.respondText("""
  29. h1 { color: olive }
  30. """, contentType = ContentType.Text.CSS)
  31. }
  32. }
  33. }

Accessing your server

Then you can point to https://127.0.0.1:8443/ to access your server.Since this is a self-signed certificate, your browser will probably warn you about an invalid certificate, soyou will have to disable that warning.

Full example

Ktor has a full example using self-signed certificates here:

https://github.com/ktorio/ktor/tree/08b173e02fe9a9dbee39f48e7162e6ea7a1f8b16/ktor-samples/ktor-samples-ssl-http2