Right now clickhouse allows to create TTL columns for Distributed tables during alters. It is working normally until server restart. After that it won't start because engine distributed doesn't support TTL clause. Modify metadata is required.

My cluster has 21.3 but tested it also with 21.11 and the same behavior.
It is blocked during create but it should be also be blocked during alters.
Tested on table from tutorial
ENGINE = Distributed('stage, 'default', 'hits_v1') 
alter table hits_v1_all modify column UTMCampaign String TTL EventDate + INTERVAL 1 MONTH ← it passes normally
bool insertQueryIdOrThrow(const String & query_id, size_t max_queries) const;
    bool insertQueryIdOrThrowNoLock(const String & query_id, size_t max_queries, const std::lock_guard<std::mutex> &) const;
    
    void removeQueryId(const String & query_id) const;
    void removeQueryIdNoLock(const String & query_id, const std::lock_guard<std::mutex> &) const;
    
    DataTypePtr getPartitionValueType() const;
    
    Block getSampleBlockWithVirtualColumns() const;
    
    
    Block getBlockWithVirtualPartColumns(const MergeTreeData::DataPartsVector & parts, bool one_part, bool ignore_empty = false) const;
    
    SimpleIncrement insert_increment;
    bool has_non_adaptive_index_granularity_parts = false;
    
    
    
    
    
    
    DataParts currently_moving_parts;
    
    mutable std::mutex moving_parts_mutex;
    PinnedPartUUIDsPtr getPinnedPartUUIDs() const;