Recently, the client’s internal test distribution platform has been reconfigured using Spring Boot+Kotlin. It used to be deployed using Tomcat, but now it is deployed using Jar packages. Since it is a relatively simple single application, Jenkins is not used for continuous integration framework. It is uploaded to the Tomcat directory through FTP and then restarts Tomcat.

Both HTTP and HTTPS are supported

I won’t mention getting SSL signatures, Google search also has a lot of free signature schemes, but I put the signature files in the Resources directory

├ ─ ─ build. Gradle ├ ─ ─ gradlew ├ ─ ─ Settings. Gradle ├ ─ ─ the SRC │ ├ ─ ─ the main │ │ ├ ─ ─ Java │ │ ├ ─ ─ kotlin │ │ ├ ─ ─ resources │ │ │ ├─ Application. Properties │ ├─ Keystore. P12Copy the code
Solution 1 (not recommended, not compatible with HTTPS and HTTP)

Modify application.properties directly

# port
server.port=8443
# signature path
server.ssl.key-store=/Users/Wiki/BetaServer/src/main/resources/keystore.p12
server.ssl.key-store-password=123123
server.ssl.keyStoreType=PKCS12
server.ssl.keyAlias:tomcat
Copy the code

Spring itself provides a very convenient way to support HTTPS. You can implement HTTPS by modifying application.properties directly, but you can’t use HTTP directly in this way.

Scheme 2 (compatible with HTTPS and HTTP)

We customize several parameters in application.properties

HTTP port #
server.port=8080
# config mode SSL
tomcat.ssl.enable=true
tomcat.ssl.key-store=keystore.p12
tomcat.ssl.key-store-password=123123
tomcat.ssl.keyStoreType=PKCS12
tomcat.ssl.port=8443
Copy the code

Since I packaged the files in Jar format and put them on the server to run, it means that the files in the resources directory cannot get the absolute path or the relative path. Instead, we read the files in the Resources directory when we start HTTPS and write them to a temporary path, so we can solve this problem.

@ConditionalOnExpression(value = "\${tomcat.ssl.enable:false}")
@Configuration
open class CustomTomcatSSLConfiguration {

    @Value("\${tomcat.ssl.port:8443}")
    private val tomcatSSLPort: Int = 0

    @Value("\${tomcat.ssl.key-store:}")
    private val tomcatSSLKeyStore: String? = null

    @Value("\${tomcat.ssl.key-store-password:}")
    private val keystorePassword: String? = null

    @Value("\${tomcat.ssl.keyStoreType:PKCS12}")
    private val keystoreType: String? = null

    @Bean
    open fun servletContainer(a): ServletWebServerFactory {
        val tomcat = TomcatServletWebServerFactory();
        tomcat.addAdditionalTomcatConnectors(createSSLConnector())
        return tomcat;
    }
    open fun createSSLConnector(a): Connector {
        // Since we need to fill in the address of the signature below, if we package as Jar, this address is invalid, read the signature file from resources
        val stream = javaClass.classLoader.getResourceAsStream(tomcatSSLKeyStore)
        // Then write the path where the current application is running
        val file = File(tomcatSSLKeyStore)
        file.writeBytes(stream.readBytes())

        val connector = Connector("org.apache.coyote.http11.Http11NioProtocol")
        connector.port = tomcatSSLPort;
        connector.secure = true
        connector.scheme = "https"

        connector.setAttribute("SSLEnabled".true)
        connector.setAttribute("sslProtocol"."TLS")
        connector.setAttribute("protocol"."org.apache.coyote.http11.Http11Protocol")
        connector.setAttribute("clientAuth".false)
        // Use the temporary preceding file path
        connector.setAttribute("keystoreFile", file.absolutePath)
        connector.setAttribute("keystoreType", keystoreType)
        connector.setAttribute("keystorePass", keystorePassword)
        connector.setAttribute("keyPass", keystorePassword)
        return connector
    }
}
Copy the code
Packaged Jar

I use Gradle instead of Maven, packaging is very convenient, directly execute command packaging

./gradlew bootJar
Copy the code
Upload the Jar to the Linux server

Jenkins has not been introduced since it is not updated frequently and will be considered later. I used to upload WAR to the server through FTP and then restart Tomcat to implement deployment. Recently I found a more convenient way to use the SCP command to upload files from the current computer to the server.

SCP - 22222 build P/libs/BetaServer jar [email protected]: / home/apps/webapp /Copy the code
Start the Jar

Jar can be started by using java-jar betaserver.jar, but when we close the command window, the process will be closed and the service will also be closed, so we need to let the service run in the background, closing the window is not affected.

nohup java -jar BetaServer.jar  > log.txt &
Copy the code

Remember not to omit the following &, the whole line is needed, log.txt is the original command line output log, we write it to the file, also convenient for us to check errors later.

Access server

Since we configured HTTP as port 8080 and HTTPS as port 8443 above, we can access it through the following command

http://100.100.100.100:8080/index
https://100.100.100.100:8443/index
Copy the code
Modifying a Port Mapping

The above access is with a port, but we published the web page, certainly can not let the user also need to input the port, the experience is too bad, we will change the HTTP port to 80, HTTPS to 443, then theoretically can achieve such access

http://100.100.100.100/index
https://100.100.100.100/index
Copy the code

The application is deployed under Linux. For security purposes, use a non-root user to start the application. The non-root user cannot listen to ports less than 1024.

java.net.SocketException: Permission denied
Copy the code

Therefore, the port forwarding mechanism of Linux is used to forward service requests to port 80 to port 8080 and port 443 to port 8443. Run the following command from root:

$ iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080
$ iptables -t nat -A PREROUTING -p tcp --dport 443 -j REDIRECT --to-port 8443
$ service iptables save
Copy the code

We’re done here.